diff --git a/.buildkite/pipelines/code_coverage/daily.yml b/.buildkite/pipelines/code_coverage/daily.yml index a2b73329b4b01..ab6fdfc29ad87 100644 --- a/.buildkite/pipelines/code_coverage/daily.yml +++ b/.buildkite/pipelines/code_coverage/daily.yml @@ -20,7 +20,7 @@ steps: - command: .buildkite/scripts/steps/code_coverage/ingest.sh label: 'Merge and Ingest' agents: - queue: c2-16 + queue: n2-4-spot depends_on: - jest - jest-integration diff --git a/.eslintrc.js b/.eslintrc.js index 221453e382802..f32b6498d9981 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -778,6 +778,11 @@ module.exports = { name: 'lodash/fp/assocPath', message: 'Please use @kbn/safer-lodash-set/fp/assocPath instead', }, + { + name: 'lodash/fp/template', + message: + 'lodash.template is unsafe, and not compatible with our content security policy.', + }, { name: 'lodash/template', message: diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b846f9a9a858d..f44a2e962f1fa 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -909,6 +909,7 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations # Kibana Platform Security /.github/codeql @elastic/kibana-security /.github/workflows/codeql.yml @elastic/kibana-security +/src/dev/eslint/security_eslint_rule_tests.ts @elastic/kibana-security /src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security /test/interactive_setup_functional/ @elastic/kibana-security @@ -1041,7 +1042,6 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations /x-pack/plugins/security_solution/server/lib/detection_engine/migrations @elastic/security-detections-response-alerts /x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview @elastic/security-detections-response-alerts /x-pack/plugins/security_solution/server/lib/detection_engine/rule_types @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/server/lib/detection_engine/signals @elastic/security-detections-response-alerts /x-pack/plugins/security_solution/server/lib/detection_engine/routes/index @elastic/security-detections-response-alerts /x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals @elastic/security-detections-response-alerts diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index a8c7eac90a359..786d5ef0ebff9 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 6b04e2c4a6157..6b5482bad9600 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 025ded9eb5cdc..6bf96b8b294b8 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index ca218c90c4192..be7ba2627c4d1 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 0864d25de28f8..1be070da0fd6c 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index af556a16ebe80..404ec374f5d93 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index eaca5d0794cc8..5c2d6f7fd9abf 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 25d722d614917..7caa2bc00fb8b 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index e3815a8ee5191..3ab0fa50805ff 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 0db7acc7b532e..122899a005d34 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index b1d87eb27a734..b4e6fecfc3cca 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 3de2fe7b744a9..a470cd5439021 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index bdba833e17856..a901c6b14ae16 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 76a14f2835c1e..a75eaeb7a2b0b 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 50b3b9041c9a1..ea6376cd43bee 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index e7ac9b03395d9..f065f7c6053c8 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 9be197a8602c0..e008179a519e2 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 91473b77d515b..f14ff89397cde 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 47b3721515638..99a0b87121e18 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index c1c1ef55a787f..f011348359e18 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 5a4b71fc48535..b341979bce4f1 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index d3ef61bf2fb6e..f84933f0b1b4e 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index f7ba2e567ec43..b2be9a6510899 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -10729,14 +10729,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/server/utils.ts" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, { "plugin": "dataViews", "path": "src/plugins/data_views/public/saved_objects_client_wrapper.ts" @@ -13567,7 +13559,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" }, { "plugin": "timelines", @@ -21190,7 +21182,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" }, { "plugin": "timelines", @@ -28514,14 +28506,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/server/utils.ts" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, { "plugin": "dataViews", "path": "src/plugins/data_views/public/saved_objects_client_wrapper.ts" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 338d9b5980fdd..717733b31880f 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index abcb0a4d94da8..2eb4ba583ca7d 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 4abac5d20fca9..55145af95934b 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index f04f9b712de71..2c803c9c2d839 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 2d307191a8d4a..79135b32e8e81 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 08d7388ddf6ab..b685ec997b5d0 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index 2ca57d5769f28..ba7f5aa586f15 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -97,7 +97,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" }, { "plugin": "timelines", @@ -8305,7 +8305,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" }, { "plugin": "timelines", @@ -15608,7 +15608,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" }, { "plugin": "timelines", @@ -25935,14 +25935,6 @@ "plugin": "data", "path": "src/plugins/data/server/query/route_handler_context.test.ts" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, { "plugin": "data", "path": "src/plugins/data/public/search/session/sessions_mgmt/lib/api.ts" diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 26def13a93d34..0ca6b88b3bb74 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 419c1f6cff505..12a25580eb6e2 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index d547cd8189a5b..ed6456585150b 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -38,11 +38,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | alerting, discover, securitySolution | - | | | actions, alerting | - | | | @kbn/core-saved-objects-migration-server-internal, actions, dataViews, data, alerting, savedObjectsTagging, savedSearch, canvas, lens, cases, graph, lists, maps, securitySolution, dashboard, visualizations, @kbn/core-test-helpers-so-type-serializer | - | -| | @kbn/core-saved-objects-common, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-api-server, @kbn/core, home, dataViews, discover, savedObjectsTagging, fleet, canvas, osquery, securitySolution, synthetics, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-import-export-server-internal, apm, savedObjectsTaggingOss, cases, lists, upgradeAssistant, savedObjectsManagement, @kbn/core-ui-settings-server-internal, dashboard | - | -| | @kbn/core-saved-objects-common, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-api-server, @kbn/core, home, dataViews, discover, savedObjectsTagging, fleet, canvas, osquery, securitySolution, synthetics, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-import-export-server-internal, apm, savedObjectsTaggingOss, cases, lists, upgradeAssistant, savedObjectsManagement, @kbn/core-ui-settings-server-internal, data | - | | | discover | - | | | data, discover, imageEmbeddable, embeddable | - | | | advancedSettings, discover | - | +| | @kbn/core-saved-objects-common, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-api-server, @kbn/core, home, dataViews, savedObjectsTagging, fleet, canvas, osquery, securitySolution, synthetics, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-import-export-server-internal, apm, savedObjectsTaggingOss, cases, lists, upgradeAssistant, savedObjectsManagement, @kbn/core-ui-settings-server-internal, dashboard | - | +| | @kbn/core-saved-objects-common, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-api-server, @kbn/core, home, dataViews, savedObjectsTagging, fleet, canvas, osquery, securitySolution, synthetics, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-import-export-server-internal, apm, savedObjectsTaggingOss, cases, lists, upgradeAssistant, savedObjectsManagement, @kbn/core-ui-settings-server-internal, data | - | | | securitySolution | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 9d7d355d36241..90479084fc698 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -564,8 +564,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | -| | [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject) | - | -| | [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=SavedObject) | - | | | [use_text_based_query_language.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts#:~:text=title), [use_text_based_query_language.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts#:~:text=title) | - | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | | | [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts#:~:text=EsQuerySearchAfter), [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts#:~:text=EsQuerySearchAfter), [get_es_query_search_after.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/context/utils/get_es_query_search_after.ts#:~:text=EsQuerySearchAfter), [get_es_query_search_after.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/context/utils/get_es_query_search_after.ts#:~:text=EsQuerySearchAfter), [get_es_query_search_after.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/context/utils/get_es_query_search_after.ts#:~:text=EsQuerySearchAfter) | - | @@ -1104,15 +1102,15 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObject), [use_security_dashboards_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx#:~:text=SavedObject), [use_security_dashboards_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx#:~:text=SavedObject), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=SavedObject), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=SavedObject), [user_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts#:~:text=SavedObject), [user_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts#:~:text=SavedObject) | - | | | [dependencies_start_mock.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts#:~:text=indexPatterns) | - | | | [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObject), [use_security_dashboards_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx#:~:text=SavedObject), [use_security_dashboards_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx#:~:text=SavedObject), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=SavedObject), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=SavedObject), [user_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts#:~:text=SavedObject), [user_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObject)+ 14 more | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [grouped_alerts.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title)+ 20 more | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [grouped_alerts.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title)+ 20 more | - | | | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.ts#:~:text=create) | - | | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch) | - | | | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [grouped_alerts.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title)+ 20 more | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [grouped_alerts.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title)+ 5 more | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [grouped_alerts.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title)+ 20 more | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [grouped_alerts.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title)+ 5 more | - | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | -| | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | +| | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts#:~:text=license%24) | 8.8.0 | | | [request_context_factory.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=authc), [route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts#:~:text=authc), [create_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts#:~:text=authc), [delete_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts#:~:text=authc), [finalize_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts#:~:text=authc), [open_close_signals_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts#:~:text=authc), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/timeline/utils/common.ts#:~:text=authc) | - | | | [use_dashboard_button_href.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/use_dashboard_button_href.ts#:~:text=savedObjects), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/index.tsx#:~:text=savedObjects), [use_security_dashboards_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx#:~:text=savedObjects), [use_create_security_dashboard_link.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/use_create_security_dashboard_link.ts#:~:text=savedObjects) | - | | | [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObjectsClientContract), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObjectsClientContract), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts#:~:text=SavedObjectsClientContract), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.test.ts#:~:text=SavedObjectsClientContract), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/dashboards/utils.test.ts#:~:text=SavedObjectsClientContract) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 02305502499e5..a4257edc748df 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -154,4 +154,4 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | --------|-------|-----------|-----------| | securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | | securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | -| securitySolution | | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | \ No newline at end of file +| securitySolution | | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts#:~:text=license%24) | 8.8.0 | \ No newline at end of file diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 9d9540e6b0074..ccf63dda93828 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index e8423d35bbb83..ddef23b4a631e 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index c33fba768a4bb..28887555fed58 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index b1d78e9b8d3e5..36b3d4dcf7acb 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 1cdcf4ccada9f..a86f88c5770a3 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 71a8c466022e9..c6159057905f2 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 7f6b86d1cffed..915fbca25d243 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index da9c2b7d10273..ac199094d61f5 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 6be30c4b8c083..93f25aafbaab0 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 58decffa6fe6b..9dc9bbfad5134 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index ad94ebccc93d4..77e029e48299c 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index b2b53c7d70703..d2cde25c51a23 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 0e1a387fa2f1f..11d527ee9f30b 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index d5d6c165b5504..04dbccdf0997f 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 9abd7f2e50b0f..286140f0d24b6 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index a7fd75ce0a600..95c8fae0e37c9 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index a145742cd3a22..692a945b7e667 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 1516f191eb0f6..a15b827070bde 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index cc49ec4ae1217..192785384e81e 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 790de63230fbb..73e7aa1f1b7e5 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 2cdc3093c14f4..caf5c83c2ab06 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 1c37e71e825b2..7ea256e85e08d 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 9594efffd6de8..247988910c3e6 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 5eb0149df1d75..b3424677d1306 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 9a644bdd0dad8..fc26a51f9c653 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 7b5d69c0a991d..5ef6733937074 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 7027ccaf727d1..8bea1b1e8715d 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 672281aeecaff..e8f573925ec16 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index d166f80c78a05..5b94fadff8259 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index f1f1844fd4a89..b916774dbdb67 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index b6ebdd8eb4686..75c2497452fab 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 4054eb91f67ce..63bc515caf0ed 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 20a199587e186..062c0047405d4 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 125c08f8400b6..768a848a4aab2 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index f1686ed9f30ab..4780f3b4c14be 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 65dbb84820ecf..c97553b7c1299 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index a779e71a96c2e..3a58461fc3584 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 5ca68b24cf326..18968689e11dd 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 7b0f2c0234e9f..d439b28ace1d2 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 59888c44bc477..626a3739cfdc0 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 034d68037c514..0fa12f26cf43e 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 95fe799982896..4824f734f9101 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 1a20b776f716c..dc8cac3bee834 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 6da9d229d4af5..d42a9f6a264a9 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 6dc544aeab105..4feef26b61869 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 0a5f2810c209f..b43b2e542aa7a 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 28ac0ed130684..83c0c9326f5e9 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 6f23309e0d12d..8444fb1c70527 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index 5345384c26a6c..5598eab2e267c 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 3087a189228ea..89b4d27e88db7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 63f482024ec0c..7ed85b3e2a725 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 1c90e9f39dfb0..3d976b803011c 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 2694a2d087a1b..293ec377ece5b 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 7d26a72b5cdb3..220c4d0eff04c 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 22e197b664a4a..375c04442cbc2 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 8fc490e4cd39b..b8ef3faac8e19 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 67d67dfb46bf6..ddf1730e45ac9 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 61e77688b28b3..3511b505e0e2f 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 585672d1dd6a6..02061af2d14dd 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 2c29b9c192069..deb309320b4bb 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index e4601b902f0b1..bf64afd743b3b 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index e7fb817cbfd05..746317a3feac4 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index a7dd3f4b2039d..b3a7d25e34933 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index a9d748f56217e..c2ae9b8a179bc 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 2803fe5f47b8e..c7dfe9733b1e1 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index f271703574607..92cc1a4550224 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index dcca4f0b98944..86b1ef2ecb1a1 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index b89dc2a704d13..849cc7d107d55 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 11567c35d7ca4..cb251ab0c54fe 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 2a3b79fa84d3c..3239215bb6adf 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 09a0077595d02..711b3e8bd807a 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 5170099bb7554..09e4ce4f3836f 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index af4f440633373..9ab4d41b30e87 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 2693d45941630..3a3df328dc8d7 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index df26cd7d214d1..81db7f3f0ab31 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index be9ecf4d3b2df..15cfcda31f131 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 0323c4ec6ec3c..eb94716c82be0 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index e52d61bd585ce..1535727bc8d26 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index bb55b75ea2a89..7347a63bc8e23 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 7cc87dc3c2f63..072e69f42cab8 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index f77ad30cb0e95..bd3b0383bc332 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index b2b34ee420bf3..993b94c6655ce 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index aa15a5c68478c..068e2faf47ed6 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 9a96304c3bfdf..721be4c216c89 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 748a64aac7869..0a109d63443f6 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 0323370d975a3..c2bc58640090a 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 3110bb52633e2..b975c09f45aaf 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 8f8b73272655a..c7e8c5b615357 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 9d62e2894da4f..f1571949332a2 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 75e0d47fa0451..e9f1270cf71fb 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index b3c799ca5d775..0ebeda8790a7c 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 6ad0c5b38b14a..4c206c74f1a8d 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index f145ba7c6065d..bcc107a33368f 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index fba7078485009..01a7e68610e7c 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index f94d0282bbb55..1de0023acef2e 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 240caacf756e7..3ed282bbfd36e 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 66524081cdfa4..c101b8c201c2c 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 5212e3ea81e58..580ff5a3b57fe 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index a391c6c8cab65..cda93ff8286cd 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 832005bc0f4ea..20ec492830d9b 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 0289172b689d0..d3df38b317fe0 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 9bec90b7e8a28..e8f9159b959a9 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 6ca97989208d8..8cf17e8a59c8b 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index b83e5f2d28ba2..8cf281aa41042 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index d1b1305883d61..1cf9cc03fd97c 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 702c1a326a392..ad46c1edd9657 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index d4832d83c7344..33f157f2a212b 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 298b4becdbd53..042e4b04bcf52 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 2df218aeb5ef0..f8d49d314c606 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 64a3b77ee5660..3857af8276b4a 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index df106e12c2ac6..ea2ea178cf45d 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 91b9681eabcf1..7d97ab37e707c 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index e82b696e83283..cf86951be6012 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 4a717d142ee77..baeb86012fd03 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 09156a4946db7..15c05311a73a5 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index d5ea2b34a8dde..9281ef198f2ee 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 926b4b6c90941..c9ea75a6c3b23 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 44ff52c273639..a4086757492e5 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index de323ede3cc66..a707b2a011962 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index a0ace7a34e511..c00e6c8f19b53 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 142828c000838..62d29a36829ee 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index fd75e0c0756b6..df6cdd92bf87e 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 38e22bbd39ea7..05859ea24e9e8 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 3a9135fd85c00..e62babd649cbf 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 44fef2eab2906..df4f5446a3094 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 59c532c88ce1d..d32765fbcfc14 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index f9bf735d3e8ef..0ec13c09b40dc 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 6abfdb26e8735..6d07e121f437f 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index eec865e0d406e..7be2d7332e660 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 82f6885c7ba72..c9a614378a360 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index bfea46a4b7ae8..14a37f5004d02 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index f9a7e416d27b2..93e0fb83aae93 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 9b18277be516a..6fdb476db5757 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index a9fa057a9a3f3..04d6d8654db89 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index a13bba16d17ea..f0fe8987be77a 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 31f46b3f4486c..bd1b8d72dbcb9 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index ecd0ccbde91bd..ff966b3d52166 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.devdocs.json b/api_docs/kbn_core_http_resources_server.devdocs.json index ac3aa3ad57cf8..a8899047410a4 100644 --- a/api_docs/kbn_core_http_resources_server.devdocs.json +++ b/api_docs/kbn_core_http_resources_server.devdocs.json @@ -513,7 +513,33 @@ "section": "def-common.KibanaErrorResponseFactory", "text": "KibanaErrorResponseFactory" }, - " & { custom | Error | Buffer | ", + " & { file | Error | Buffer | ", + "Stream", + " | { message: string | Error; attributes?: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.ResponseErrorAttributes", + "text": "ResponseErrorAttributes" + }, + " | undefined; } | undefined>(options: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.FileHttpResponseOptions", + "text": "FileHttpResponseOptions" + }, + "): ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.IKibanaResponse", + "text": "IKibanaResponse" + }, + "; custom | Error | Buffer | ", "Stream", " | { message: string | Error; attributes?: ", { diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index d174fc60620e6..d2e0cc08f2eb4 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index f2282e1c3e802..2bae75d9a5c77 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.devdocs.json b/api_docs/kbn_core_http_resources_server_mocks.devdocs.json index c8bdc7c3f7473..12acbace23682 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.devdocs.json +++ b/api_docs/kbn_core_http_resources_server_mocks.devdocs.json @@ -721,6 +721,58 @@ "section": "def-common.IKibanaResponse", "text": "IKibanaResponse" }, + "); file: jest.MockInstance<", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.IKibanaResponse", + "text": "IKibanaResponse" + }, + ", [options: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.FileHttpResponseOptions", + "text": "FileHttpResponseOptions" + }, + " | Error | Buffer | ", + "Stream", + " | { message: string | Error; attributes?: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.ResponseErrorAttributes", + "text": "ResponseErrorAttributes" + }, + " | undefined; } | undefined>]> & ( | Error | Buffer | ", + "Stream", + " | { message: string | Error; attributes?: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.ResponseErrorAttributes", + "text": "ResponseErrorAttributes" + }, + " | undefined; } | undefined>(options: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.FileHttpResponseOptions", + "text": "FileHttpResponseOptions" + }, + ") => ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.IKibanaResponse", + "text": "IKibanaResponse" + }, "); custom: jest.MockInstance<", { "pluginId": "@kbn/core-http-server", diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 6eb7ab4b5813a..6daa81af7f719 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.devdocs.json b/api_docs/kbn_core_http_router_server_internal.devdocs.json index ee67394ec6432..f3b8701d3798e 100644 --- a/api_docs/kbn_core_http_router_server_internal.devdocs.json +++ b/api_docs/kbn_core_http_router_server_internal.devdocs.json @@ -379,6 +379,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-common.kibanaResponseFactory.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/core-http-router-server-internal", "id": "def-common.kibanaResponseFactory.custom", diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index bb18a70e25410..5abfd211d3f55 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 25 | 5 | 25 | 1 | +| 26 | 6 | 26 | 1 | ## Common diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 9fde234905af1..9c6b7735df4fd 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index 35891c964b6d2..24328cd2e9a6b 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -788,6 +788,148 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions", + "type": "Interface", + "tags": [], + "label": "FileHttpResponseOptions", + "description": [ + "\nHTTP response parameters for a response with adjustable status code." + ], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.FileHttpResponseOptions", + "text": "FileHttpResponseOptions" + }, + "" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.body", + "type": "Uncategorized", + "tags": [], + "label": "body", + "description": [ + "Attachment content to send to the client" + ], + "signature": [ + "T" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.filename", + "type": "string", + "tags": [], + "label": "filename", + "description": [ + "Attachment name, encoded and added to the headers to send to the client" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.fileContentType", + "type": "CompoundType", + "tags": [], + "label": "fileContentType", + "description": [ + "Explicitly set the attachment content type. Tries to detect the type based on extension and defaults to application/octet-stream" + ], + "signature": [ + "string | null | undefined" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.fileContentSize", + "type": "number", + "tags": [], + "label": "fileContentSize", + "description": [ + "Attachment content size in bytes, Tries to detect the content size from body" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.headers", + "type": "CompoundType", + "tags": [], + "label": "headers", + "description": [ + "HTTP Headers with additional information about response" + ], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.ResponseHeaders", + "text": "ResponseHeaders" + }, + " | undefined" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.bypassErrorFormat", + "type": "CompoundType", + "tags": [], + "label": "bypassErrorFormat", + "description": [ + "Bypass the default error formatting" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.FileHttpResponseOptions.bypassFileNameEncoding", + "type": "CompoundType", + "tags": [], + "label": "bypassFileNameEncoding", + "description": [ + "Bypass filename encoding, only set to true if the filename is already encoded" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/http/core-http-server/src/router/response.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-http-server", "id": "def-common.HttpAuth", @@ -7520,7 +7662,33 @@ "section": "def-common.KibanaErrorResponseFactory", "text": "KibanaErrorResponseFactory" }, - " & { custom | Error | Buffer | ", + " & { file | Error | Buffer | ", + "Stream", + " | { message: string | Error; attributes?: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.ResponseErrorAttributes", + "text": "ResponseErrorAttributes" + }, + " | undefined; } | undefined>(options: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.FileHttpResponseOptions", + "text": "FileHttpResponseOptions" + }, + "): ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.IKibanaResponse", + "text": "IKibanaResponse" + }, + "; custom | Error | Buffer | ", "Stream", " | { message: string | Error; attributes?: ", { diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index e7f1b329a662d..7132683763250 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 403 | 1 | 160 | 0 | +| 411 | 1 | 160 | 0 | ## Common diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index fc4f5ee7456cf..974f85a8b55f7 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 47c15fe4b67f6..0bfca6e59b368 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index be26fff16538b..47db66b5ecc84 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index d385ae73f44a3..c27bfbd37feac 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 5b370336e2728..09dae1b2abf1b 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 1bb7b5a34443b..6d56e08c115c5 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 70ff40d64deb0..9ae37a90003a0 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 438800d2da4cd..a1f7cb96252a7 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 7ca275f6cf506..80e25386fc84b 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 47098584cd3b8..1011becb38e39 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 8f17e2ea21e34..610ccc9db4916 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index 2fbf40fcbbfb5..035371808b5f4 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index 5fa83bca9948a..2ed4f5fef2db3 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index cd11d7b7c5005..562f7f28c60f8 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 0ee80f80a2d16..1eb48afd95a2b 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 2102681fd91e7..327d6e7a3ce5a 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.devdocs.json b/api_docs/kbn_core_logging_server.devdocs.json index 3341d022e8280..edacae8c2aa44 100644 --- a/api_docs/kbn_core_logging_server.devdocs.json +++ b/api_docs/kbn_core_logging_server.devdocs.json @@ -223,7 +223,7 @@ "label": "level", "description": [], "signature": [ - "\"error\" | \"off\" | \"all\" | \"debug\" | \"info\" | \"warn\" | \"trace\" | \"fatal\"" + "\"error\" | \"all\" | \"off\" | \"debug\" | \"info\" | \"warn\" | \"trace\" | \"fatal\"" ], "path": "packages/core/logging/core-logging-server/src/logger.ts", "deprecated": false, diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 876c8b64945c0..83d8ea5c57490 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.devdocs.json b/api_docs/kbn_core_logging_server_internal.devdocs.json index d304656de7192..fd6f6dc3b8731 100644 --- a/api_docs/kbn_core_logging_server_internal.devdocs.json +++ b/api_docs/kbn_core_logging_server_internal.devdocs.json @@ -199,7 +199,7 @@ "section": "def-common.Type", "text": "Type" }, - "[]>; }>" + "[]>; }>" ], "path": "packages/core/logging/core-logging-server-internal/src/logging_config.ts", "deprecated": false, @@ -247,7 +247,7 @@ "section": "def-common.Type", "text": "Type" }, - "<\"error\" | \"off\" | \"all\" | \"debug\" | \"info\" | \"warn\" | \"trace\" | \"fatal\">; }>" + "<\"error\" | \"all\" | \"off\" | \"debug\" | \"info\" | \"warn\" | \"trace\" | \"fatal\">; }>" ], "path": "packages/core/logging/core-logging-server-internal/src/logging_config.ts", "deprecated": false, diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index bc74ecdc7e544..c1d2cb23e5972 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index e38d819f7e00f..a4b7482bfe9e8 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 16c66ea9c487f..92b8f41da6d32 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index eb09ded282878..af3e01e6ece08 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 31cd8c5e705de..0e40b26c24c4c 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 233b6cd9765de..6e00b954efbb7 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index d9f011a03ab9c..a238d378d5c79 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 1c638477a4b32..9c0ab3290114f 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index bb269fa85d2aa..278c9eddb7fc4 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 1895f0412a792..681584152552f 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 0656207d6def8..af63729ff7af0 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index b4eae996ccdee..f232dc1095c47 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 78451dc0fe5bf..704727e17650c 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 9d1689645a745..7302144640fee 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index d8939782ebcd0..f3f74033f0690 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index d96117c70e71b..dae2144fd0091 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index ceed5cf00c45a..bde023a91ebb5 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index f4c117a8fce3e..36b8d050f77d5 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 3a60a3ba16d16..019e64ab0b420 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 8cbba561be3b1..bff0a2571ea11 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 67fa763ece2e8..e9e97ad4ac7ba 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 5156d35291b84..be617032639b4 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index ce378e61cbdd6..e99e6c1cb1a3e 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index aed390d505642..fd4876fb7217e 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index d6b4438c0a0d5..05083a9379a4d 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 7088ad36e3829..9a1b0c18751f7 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index deb547919dc0c..cc1550490e12f 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 35da19ac779bd..5a6fe5d1dc482 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index da967ecae831e..3eedd0bf046a0 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index acaf0d45a22e4..26e8db451e83a 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 4d1152439ec3c..eec7b798a06c1 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 8cf1c19d0c0c3..1f86a3cecacdc 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 8f4fad88ed1d3..d36afdadf0cbd 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 24603ff1d51dc..36259efd2ef5a 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 46c9966dc6af8..f84981449ddf2 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index d8f8bb96d6277..5228ef48d73d9 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.devdocs.json b/api_docs/kbn_core_saved_objects_common.devdocs.json index 584a69cfcb136..0c231f1ff4878 100644 --- a/api_docs/kbn_core_saved_objects_common.devdocs.json +++ b/api_docs/kbn_core_saved_objects_common.devdocs.json @@ -1275,14 +1275,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/server/utils.ts" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" - }, { "plugin": "dataViews", "path": "src/plugins/data_views/public/saved_objects_client_wrapper.ts" diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 377f7a81143de..5db946fd1fc84 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index be6e4045e9ae2..66ce8098c17c7 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 132feaf4ef2dd..e7695de2d2b2f 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index fc88132d01237..aaa6da1d1ce75 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index e62c08ad469a1..190de89e284e3 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index a51ac3d5fd437..1997dd7e500a1 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 01a7f11b61272..ad88d3434c93b 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 12fa2b5789b0d..e019befaf4778 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 6cac1a931a779..a3cdd465231a2 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index cf82e73fc9fbc..db13569fc15a5 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index ab7a55f1acdbf..e98ac07a6eb86 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index ba19929284e6d..184613b2bd134 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 3c67b97a24f12..8ee1bcb32622d 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 06a111ebbd15a..a72c75b0a892c 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 193b5a6598a05..e16d7583efcd8 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index e6c6c389737c2..1a08b1250ecf2 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 9cc8a6c47ebee..7fc2878ad1206 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index fd801604bed7b..eda623498db60 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 2f704410ee1fa..447c495ff4ccd 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index d110b93bd9952..175e1ed9bab85 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index a38fd54631ce5..35c6273c61213 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 806f4844aeb49..3b22b27f1997a 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index b3977691745f7..f3406378d00d4 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 4ee966c270caf..76e920393bb73 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 3fff3eeeb4334..66666a05ffe19 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 5bbde6b8b3183..927468797587b 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 8dccaed91cf51..71cb58aad9b56 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index d5bb99e76b4bb..56d22396db1b6 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 93ab9341ab870..78bad8c43e148 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 0c40275e03357..9c2262467058a 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index c793b06744f31..588d770ab0f57 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index e32825076deb6..d5dda260a906e 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 1977b73ee116f..02386cdf929e1 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index a35e6926461ad..d7193bced5849 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 4ff2cecd4f956..53c2e496b6b2e 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index ee4d298ef31ec..2e5a072cf7495 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 2a16e238cef76..b08d3e2f1a0eb 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 24dab3e60d63a..658fd80529198 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 517edf0fa6139..1513bbc31f7a0 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index f697f46bd1ac7..5e9fb3d83fde2 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 90cb7ac08cbbf..415e48f690346 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index d924076d1937d..a9f89a9888a86 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 229901545bea2..21787f427307a 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 8bcfb29e75fa4..552ef1cd7001e 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 4ad68bc29bc76..5c8cc814ac584 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 2aeb99c795204..fecb21184b8a1 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 9f8692d4a6424..784763e15d41d 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 7bba0de96c552..ba77b55460365 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 60e69392e7086..8234d3212999f 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index f0267b086e10f..273601e75d946 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index a8cea39697b20..eaa59a2eea258 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index c783772d02e38..0287d21eb53df 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 2f717beed84d8..8d3dbec5ef1d4 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index d2cf15c7c688d..17c629d017633 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index b8f3c42b989cf..aee0d8aa6d524 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 4fd60fc3bd911..27c485203f114 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 75b8bca841974..adb6e8aa995fd 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index f7c3c9eae2564..508e8edcf7812 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 82ef7a96524d6..65fe99bcf0fd6 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index e2b567bf7f094..cb682ae4f9900 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index a60b6ba6837df..9d5c6575fdd70 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 8ec80ab05adb5..093991e202a75 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index c9c77e352702f..f3147c2dfe769 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index dd04af7086bf1..021576539dda5 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 28e033e185560..9a26721488b93 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 1a28366e71d39..2f4a023579df9 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index f702607611a45..a3c25d75910b4 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 2f5d09d21a292..78c93dc47e995 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index c3724b1a137de..23162fdbcb8a0 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 49d46e3416e19..7ab510e97ac36 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 2052522f82a79..5a4aac9574156 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index e7a5072c55a43..406cfb327294e 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 2d336de09a536..8aa1631ce53a0 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 4c5e83eea5a1d..c13e84f344705 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index bda050458b545..53359db3b93a4 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index d036d70d12bd3..8bb33f2663dc2 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 11c7c295d8a63..2f2cd5efe78bc 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index fb83bcf3d18a8..ebd371fa39360 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 0d85e5ab93e5c..1d634f80ec520 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 6b88d63acce87..1691190226d46 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 23a8de36269d8..bcee4b75b6c2a 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 81aa29ed89598..09ed1ad02393c 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 3d958f1622125..f9c4d29869a7f 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 765778e9f60a3..d804c533e1b09 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 41a98d17c8868..3638a55e2ad02 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index f68c5ea66be19..8f216afa89398 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 4cb3f92ca692c..5de6feece7499 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index d508c25208f11..1701080c152a4 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 03df0bf6bcf8b..c89cd61bfdc71 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 4e4edd005102c..db2b66505446a 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 8aca156d804d9..3f547dc9a9278 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index f33554a0e5032..ab6126edfa1d0 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 511e8afc3a444..2ce4e25fe73dd 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 0042b420e67d1..27117caad1c2a 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index d207320cc3a91..07dcc95444a77 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index a8872964ee545..da2e98c4fb0fa 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 1b402275347f3..1656d07cb758c 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 17fd2d4a76c16..24bbcf7806d47 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 22263b8e4e322..280afbc3028e4 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 56e3ec27cd761..b52227497982a 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 93ee488473754..5e2dbdeb7c034 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 44e86adf6a4bc..d610a4cd3eb85 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index c3207f3b500f0..50ca1b14e44a3 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index e14b9170d12f5..dcb989b2881ad 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 014d0c6b6a4a6..35b7b45d54e6f 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 32b37e20542f2..085842ffd707e 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 4cf5c4b3a41f9..7e355cc10b8dc 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 35778f08d40a5..cd458e3bd8070 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 0b00ad6b6d40c..27628ddca800f 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index fb7c35cf4d01c..b33fa79e75be6 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 5a1a4d567e5c7..85723f920c3b1 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 1b264ca791f89..8d1de91435814 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index a14f7a9ce942c..58f76d4772be0 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 1a7d2cb71c137..919c81d834263 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index ff9ece5c2f896..e069f4f2a258f 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index c3b864038fc50..c1ea8d74f6da6 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index ce8fe25e6245e..4673569b1f4e1 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 32a76fe017a17..bc065cf2a4cba 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index b2b8838f66d8f..d553b227b1143 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index f01105353b459..4a39bf9fb3c9e 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index a09b116480286..c7deece2ea113 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.devdocs.json b/api_docs/kbn_shared_ux_button_toolbar.devdocs.json index 67ad616db880e..57ab85b6c5e8e 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.devdocs.json +++ b/api_docs/kbn_shared_ux_button_toolbar.devdocs.json @@ -119,15 +119,15 @@ }, { "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.PrimaryButton", + "id": "def-common.Toolbar", "type": "Function", "tags": [], - "label": "PrimaryButton", + "label": "Toolbar", "description": [ - "\nA primary action button, usually appearing first in the toolbar." + "\n" ], "signature": [ - "({ label, iconSide, ...rest }: ", + "({ children }: ", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -137,16 +137,16 @@ }, ") => JSX.Element" ], - "path": "packages/shared-ux/button_toolbar/src/buttons/primary/primary.tsx", + "path": "packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.PrimaryButton.$1", + "id": "def-common.Toolbar.$1", "type": "Object", "tags": [], - "label": "{ label, iconSide = 'left', ...rest }", + "label": "{ children }", "description": [], "signature": [ { @@ -157,26 +157,26 @@ "text": "Props" } ], - "path": "packages/shared-ux/button_toolbar/src/buttons/primary/primary.tsx", + "path": "packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true } ], - "returnComment": [], + "returnComment": [ + "Toolbar component" + ], "initialIsOpen": false }, { "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.Toolbar", + "id": "def-common.ToolbarButton", "type": "Function", "tags": [], - "label": "Toolbar", - "description": [ - "\n" - ], + "label": "ToolbarButton", + "description": [], "signature": [ - "({ children }: ", + "({ label, type, iconSide, ...rest }: React.PropsWithChildren<", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -184,37 +184,37 @@ "section": "def-common.Props", "text": "Props" }, - ") => JSX.Element" + ">) => JSX.Element" ], - "path": "packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx", + "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.Toolbar.$1", - "type": "Object", + "id": "def-common.ToolbarButton.$1", + "type": "CompoundType", "tags": [], - "label": "{ children }", + "label": "{\n label,\n type = 'empty',\n iconSide = 'left',\n ...rest\n}", "description": [], "signature": [ + "React.PropsWithChildren<", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", "docId": "kibKbnSharedUxButtonToolbarPluginApi", "section": "def-common.Props", "text": "Props" - } + }, + ">" ], - "path": "packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx", + "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true } ], - "returnComment": [ - "Toolbar component" - ], + "returnComment": [], "initialIsOpen": false }, { @@ -227,7 +227,7 @@ "\nA button which opens a popover of additional actions within the toolbar." ], "signature": [ - "({ label, iconType, children, iconSide, ...popover }: ", + "({ type, label, iconType, children, ...popover }: ", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -246,7 +246,7 @@ "id": "def-common.ToolbarPopover.$1", "type": "CompoundType", "tags": [], - "label": "{ label, iconType, children, iconSide, ...popover }", + "label": "{ type, label, iconType, children, ...popover }", "description": [], "signature": [ { @@ -343,6 +343,22 @@ "path": "packages/shared-ux/button_toolbar/src/buttons/icon_button_group/icon_button_group.tsx", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-button-toolbar", + "id": "def-common.IconButton.datatestsubj", + "type": "string", + "tags": [], + "label": "'data-test-subj'", + "description": [ + "Test subject for button" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/shared-ux/button_toolbar/src/buttons/icon_button_group/icon_button_group.tsx", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -418,9 +434,9 @@ }, " extends Pick<", "EuiButtonPropsForButton", - ", \"onClick\" | \"iconType\" | \"iconSide\">" + ", \"data-test-subj\" | \"onClick\" | \"iconType\" | \"iconSide\">" ], - "path": "packages/shared-ux/button_toolbar/src/buttons/primary/primary.tsx", + "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -431,7 +447,21 @@ "tags": [], "label": "label", "description": [], - "path": "packages/shared-ux/button_toolbar/src/buttons/primary/primary.tsx", + "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-button-toolbar", + "id": "def-common.Props.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "ToolbarButtonTypes | undefined" + ], + "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", "deprecated": false, "trackAdoption": false } @@ -479,7 +509,7 @@ "label": "Props", "description": [], "signature": [ - "{ onClick?: React.MouseEventHandler | undefined; iconSide?: ", + "{ 'data-test-subj'?: string | undefined; onClick?: React.MouseEventHandler | undefined; iconSide?: ", "ButtonContentIconSide", "; }" ], @@ -507,15 +537,15 @@ }, { "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.ToolbarButton", + "id": "def-common.ToolbarButtonType", "type": "Type", "tags": [], - "label": "ToolbarButton", + "label": "ToolbarButtonType", "description": [ "type for cases with both button or a popover could be used" ], "signature": [ - "(({ label, iconSide, ...rest }: ", + "React.FunctionComponent<", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -523,7 +553,7 @@ "section": "def-common.Props", "text": "Props" }, - ") => JSX.Element) | (({ label, iconType, children, iconSide, ...popover }: ", + "> | (({ type, label, iconType, children, ...popover }: ", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 1d43b1a57f4f4..fa35a43514eeb 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 25 | 0 | 8 | 0 | +| 27 | 0 | 10 | 0 | ## Common diff --git a/api_docs/kbn_shared_ux_card_no_data.devdocs.json b/api_docs/kbn_shared_ux_card_no_data.devdocs.json index 54defc33a74eb..8c7dec127aee0 100644 --- a/api_docs/kbn_shared_ux_card_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data.devdocs.json @@ -188,7 +188,7 @@ "Interpolation", "<", "Theme", - ">; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: Booleanish | \"inherit\" | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; spellCheck?: Booleanish | undefined; tabIndex?: number | undefined; translate?: \"yes\" | \"no\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; security?: string | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"time\" | \"true\" | \"false\" | \"step\" | \"location\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"dialog\" | \"menu\" | \"true\" | \"false\" | \"grid\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"all\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"ascending\" | \"descending\" | \"other\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChange?: React.FormEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; paddingSize?: \"m\" | \"none\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined; href?: string | undefined; rel?: string | undefined; target?: string | undefined; icon?: React.ReactElement<", + ">; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: Booleanish | \"inherit\" | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; spellCheck?: Booleanish | undefined; tabIndex?: number | undefined; translate?: \"yes\" | \"no\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; security?: string | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"time\" | \"true\" | \"false\" | \"step\" | \"location\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"dialog\" | \"menu\" | \"true\" | \"false\" | \"grid\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"all\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"ascending\" | \"descending\" | \"other\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChange?: React.FormEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; paddingSize?: \"m\" | \"none\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined; href?: string | undefined; rel?: string | undefined; target?: string | undefined; icon?: React.ReactElement<", "EuiIconProps", ", string | React.JSXElementConstructor> | null | undefined; hasBorder?: boolean | undefined; textAlign?: \"right\" | \"left\" | \"center\" | undefined; titleElement?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"span\" | undefined; titleSize?: \"s\" | \"xs\" | undefined; betaBadgeProps?: (", "CommonProps", diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index f683ed628278a..3586f053ac47f 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 6050cf5fe7b3a..2e1bffe344d14 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 88a4cccc3fc1f..bae037be686b5 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index f82ddbbcb7b43..4dffa9c1aef61 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index f4408f3c71846..69bfe48a537c0 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 4c9c9326048eb..6ffefddd67b1e 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 754f3b159cf4c..c84800f82883a 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index d65dfc38473ae..613cc2d6800b4 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index fad8d5485e3fd..49cba5b2b6b35 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index d19e767339b1f..bc4cd4bb296af 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 7432f643ae04b..a1832fbd6b9d0 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index b87cc7024c466..69a7fadee3a7c 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json b/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json index e6fca98d31d64..1dbb1d5e4e58e 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json +++ b/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json @@ -439,7 +439,7 @@ "Interpolation", "<", "Theme", - ">; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: Booleanish | \"inherit\" | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; spellCheck?: Booleanish | undefined; tabIndex?: number | undefined; translate?: \"yes\" | \"no\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; color?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; security?: string | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"time\" | \"true\" | \"false\" | \"step\" | \"location\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"dialog\" | \"menu\" | \"true\" | \"false\" | \"grid\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"all\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"ascending\" | \"descending\" | \"other\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChange?: ((value: string) => void) | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; height?: number | \"full\" | undefined; readOnly: boolean; maxHeight?: number | undefined; autoExpandPreview?: boolean | undefined; parsingPluginList?: ", + ">; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: Booleanish | \"inherit\" | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; spellCheck?: Booleanish | undefined; tabIndex?: number | undefined; translate?: \"yes\" | \"no\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; color?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; security?: string | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"time\" | \"true\" | \"false\" | \"step\" | \"location\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"dialog\" | \"menu\" | \"true\" | \"false\" | \"grid\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"all\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"ascending\" | \"descending\" | \"other\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChange?: ((value: string) => void) | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; height?: number | \"full\" | undefined; readOnly: boolean; maxHeight?: number | undefined; autoExpandPreview?: boolean | undefined; parsingPluginList?: ", "PluggableList", "<", "Settings", diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 764878abdfcb3..7d39cc8ff942d 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 2293dc101a15d..4d299d8c283c8 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index d158d0e8e2cae..1b96b08fa1505 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index f45ad747bc01f..41e4b50335f26 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index b2cb7de551e04..0b5f529b6fc2e 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index b14c98e78d175..c092d3a7327e9 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 3aabe079d476c..5d3e545e34a9a 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 76fd18513dfc3..e99ba437ea181 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 63b6a39fd4908..e473873e76f9c 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 764ec81558bdf..24adfbf9bab9a 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index bfb146963ac37..f374066c21e10 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 88e5cf3681b27..b8c62ed4bc494 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index d8b456898e35a..c84c8dd68cbdb 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index f89abc57b9d4d..6a617b21a10a9 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index e86c4bce47e0d..e7c675c73947d 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 55934a0c4fb46..287c4f3b7c580 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 4f4ef700937ad..52347ab66f141 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index b381ae504adee..d8a7f1f9b7677 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 5fda79ab07341..570ef34b459c4 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 2f82394e1c93d..2d2152989cec8 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index fb06c122e9a3e..3d2fba338fcd2 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index e51d84c33a748..926afb71749c5 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 0a5ac6c5054e1..783c0f7c701e2 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 35a461ef34c87..e053e5ac872b2 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 182edd35509bb..9f9241b66735f 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 815db39a8daa3..b5bfc34bfffce 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 31392f03faaa1..e2558983fbebe 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index c7cfa1e9bb199..d843cfc415389 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index fd1c69a6a9585..557f0858d2f54 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 5314e011cd4cc..bf45f0616677f 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 13144dd73ef4b..8fd07a8394192 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index a5748680c6d37..30c08ee3d477b 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index d3baa593c049e..b7972e4cee4f9 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index cff99a2393194..8b66ee98cff48 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 47962129051be..b21e5ef9bd09d 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 3b9de3d1e8f19..7434590f401f9 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 18043d4309c53..bf7caa13eda59 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 54a5977d0be0d..76e3f26b7df27 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index b0b193d55c4b6..eb3497195d0ae 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 53f1caf239ff4..070ac1c4a6068 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index b4b5a8a3e1cf3..73eda7bda3a96 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index ffdc78158061a..6bf0149dfebb0 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index b9fe36bfe2994..2e54a482ecfa0 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index cbfcd9fc04e6b..072f6b890c97f 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 7c4a97841cb38..ee4da3c15af13 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 7f9ebb06b4a42..9ca9dc4debbbe 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 425fdee9c50a0..49b8bee6aea9c 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.devdocs.json b/api_docs/licensing.devdocs.json index 2d6936944a2d3..f83a3f0c03d25 100644 --- a/api_docs/licensing.devdocs.json +++ b/api_docs/licensing.devdocs.json @@ -2172,7 +2172,7 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts" }, { "plugin": "snapshotRestore", diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index e35c593bc9f45..9ba9e133f0eba 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index bb3a81a91e5fa..9e7a02cf6a059 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 661da08971666..b8a6b1c234a32 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index c001bf49fe80d..2de6fd928dbb4 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 06e597b5c7cca..6ca708031eb71 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.devdocs.json b/api_docs/ml.devdocs.json index 4b0ded96dddb0..6d4c171c7664b 100644 --- a/api_docs/ml.devdocs.json +++ b/api_docs/ml.devdocs.json @@ -414,6 +414,23 @@ ], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "ml", + "id": "def-public.useMlNodeAvailableCheck", + "type": "Function", + "tags": [], + "label": "useMlNodeAvailableCheck", + "description": [], + "signature": [ + "() => { mlNodesAvailable: boolean; isCloud: boolean; deploymentId: string | null; isCloudTrial: boolean; }" + ], + "path": "x-pack/plugins/ml/public/application/components/node_available_warning/hooks.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [ diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 4915f7880fd62..84d73e1cc383c 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 258 | 9 | 82 | 40 | +| 259 | 9 | 83 | 40 | ## Client diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index f860692b59c2d..38b9c7b4b4a02 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index a94071d4cf742..56d67962cddb2 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index ac4f834059efd..cfad19cb77150 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 7dc045082e738..4300df9620dfa 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 3f228cc308484..f5423d859c0c8 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 264878856ef5e..ad380f21e8a89 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 74e88598ca9da..b3e3702b98a01 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 8a9718ddec121..241f72e86a5f0 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 67709 | 514 | 58539 | 1238 | +| 67704 | 515 | 58526 | 1238 | ## Plugin Directory @@ -121,7 +121,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 41 | 0 | 41 | 6 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 267 | 0 | 266 | 27 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 67 | 0 | 67 | 0 | -| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 258 | 9 | 82 | 40 | +| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 259 | 9 | 83 | 40 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 15 | 3 | 13 | 1 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 9 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 34 | 0 | 34 | 2 | @@ -130,7 +130,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 625 | 43 | 619 | 34 | | | [@elastic/security-defend-workflows](https://github.com/orgs/elastic/teams/security-defend-workflows) | - | 24 | 0 | 24 | 7 | | painlessLab | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | -| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 219 | 7 | 163 | 12 | +| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 202 | 7 | 146 | 12 | | | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 15 | 2 | 15 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 36 | 0 | 16 | 0 | @@ -295,9 +295,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 7 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 3 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 25 | 5 | 25 | 1 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 26 | 6 | 26 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 1 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 403 | 1 | 160 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 411 | 1 | 160 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 55 | 0 | 49 | 6 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 41 | 0 | 40 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 2 | 0 | @@ -472,7 +472,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 40 | 0 | 3 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 8 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 13 | 0 | 9 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 25 | 0 | 8 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 27 | 0 | 10 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 28 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 5 | 0 | 4 | 0 | diff --git a/api_docs/presentation_util.devdocs.json b/api_docs/presentation_util.devdocs.json index 7f53e919c56ab..6874d21e658ae 100644 --- a/api_docs/presentation_util.devdocs.json +++ b/api_docs/presentation_util.devdocs.json @@ -568,41 +568,6 @@ } ], "functions": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.AddFromLibraryButton", - "type": "Function", - "tags": [], - "label": "AddFromLibraryButton", - "description": [], - "signature": [ - "({ onClick, ...rest }: ", - "Props", - ") => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/add_from_library.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.AddFromLibraryButton.$1", - "type": "Object", - "tags": [], - "label": "{ onClick, ...rest }", - "description": [], - "signature": [ - "Props" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/add_from_library.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "presentationUtil", "id": "def-public.cleanFiltersForSerialize", @@ -1038,113 +1003,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.PrimaryActionButton", - "type": "Function", - "tags": [], - "label": "PrimaryActionButton", - "description": [], - "signature": [ - "({ isDarkModeEnabled, ...props }: ", - "Props", - ") => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.PrimaryActionButton.$1", - "type": "Object", - "tags": [], - "label": "{ isDarkModeEnabled, ...props }", - "description": [], - "signature": [ - "Props" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.PrimaryActionPopover", - "type": "Function", - "tags": [], - "label": "PrimaryActionPopover", - "description": [], - "signature": [ - "(props: Omit<", - "Props", - ", \"primary\">) => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/primary_popover.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.PrimaryActionPopover.$1", - "type": "Object", - "tags": [], - "label": "props", - "description": [], - "signature": [ - "Omit<", - "Props", - ", \"primary\">" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/primary_popover.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.QuickButtonGroup", - "type": "Function", - "tags": [], - "label": "QuickButtonGroup", - "description": [], - "signature": [ - "({ buttons }: ", - "Props", - ") => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.QuickButtonGroup.$1", - "type": "Object", - "tags": [], - "label": "{ buttons }", - "description": [], - "signature": [ - "Props" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "presentationUtil", "id": "def-public.registerExpressionsLanguage", @@ -1197,111 +1055,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.SolutionToolbar", - "type": "Function", - "tags": [], - "label": "SolutionToolbar", - "description": [], - "signature": [ - "({ isDarkModeEnabled, children }: ", - "Props", - ") => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.SolutionToolbar.$1", - "type": "Object", - "tags": [], - "label": "{ isDarkModeEnabled, children }", - "description": [], - "signature": [ - "Props" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.SolutionToolbarButton", - "type": "Function", - "tags": [], - "label": "SolutionToolbarButton", - "description": [], - "signature": [ - "({ label, primary, className, ...rest }: ", - "Props", - ") => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/button.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.SolutionToolbarButton.$1", - "type": "Object", - "tags": [], - "label": "{ label, primary, className, ...rest }", - "description": [], - "signature": [ - "Props" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/button.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.SolutionToolbarPopover", - "type": "Function", - "tags": [], - "label": "SolutionToolbarPopover", - "description": [], - "signature": [ - "({ label, iconType, primary, iconSide, children, ...popover }: ", - "Props", - ") => JSX.Element" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/popover.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.SolutionToolbarPopover.$1", - "type": "CompoundType", - "tags": [], - "label": "{\n label,\n iconType,\n primary,\n iconSide,\n children,\n ...popover\n}", - "description": [], - "signature": [ - "Props" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/popover.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "presentationUtil", "id": "def-public.useLabs", @@ -2158,59 +1911,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.QuickButtonProps", - "type": "Interface", - "tags": [], - "label": "QuickButtonProps", - "description": [], - "signature": [ - { - "pluginId": "presentationUtil", - "scope": "public", - "docId": "kibPresentationUtilPluginApi", - "section": "def-public.QuickButtonProps", - "text": "QuickButtonProps" - }, - " extends Pick<", - "EuiButtonGroupOptionProps", - ", \"iconType\">" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "presentationUtil", - "id": "def-public.QuickButtonProps.createType", - "type": "string", - "tags": [], - "label": "createType", - "description": [], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "presentationUtil", - "id": "def-public.QuickButtonProps.onClick", - "type": "Function", - "tags": [], - "label": "onClick", - "description": [], - "signature": [ - "() => void" - ], - "path": "src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - } - ], - "initialIsOpen": false - }, { "parentPluginId": "presentationUtil", "id": "def-public.ReduxEmbeddablePackage", diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 2f742ca4de01c..2e4c690bdfde2 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 219 | 7 | 163 | 12 | +| 202 | 7 | 146 | 12 | ## Client diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index d74003c9e01f0..4e7eff9bad9ea 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index cad1a4fbb1341..50384f02b70fd 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 44ff5fb23ad97..d22bdb346e94b 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 542c26a5a0a29..9b051aa152030 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index d27f7993eefe5..01e03df7443c0 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index bdf00ed48db5e..d97cab5c93af0 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 4e71d6272a325..174da172a54e0 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index ddf340bfb0255..0ab98d7d02ba1 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.devdocs.json b/api_docs/saved_objects_management.devdocs.json index a6df92789fef9..62057eb5bdb1c 100644 --- a/api_docs/saved_objects_management.devdocs.json +++ b/api_docs/saved_objects_management.devdocs.json @@ -308,7 +308,7 @@ "Interpolation", "<", "Theme", - ">; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: Booleanish | \"inherit\" | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; spellCheck?: Booleanish | undefined; tabIndex?: number | undefined; translate?: \"yes\" | \"no\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; color?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; security?: string | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"time\" | \"true\" | \"false\" | \"step\" | \"location\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"dialog\" | \"menu\" | \"true\" | \"false\" | \"grid\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"all\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"ascending\" | \"descending\" | \"other\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChange?: React.FormEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; field: (string & {}) | keyof ", + ">; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: Booleanish | \"inherit\" | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; spellCheck?: Booleanish | undefined; tabIndex?: number | undefined; translate?: \"yes\" | \"no\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; color?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; security?: string | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"time\" | \"true\" | \"false\" | \"step\" | \"location\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"dialog\" | \"menu\" | \"true\" | \"false\" | \"grid\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"all\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"ascending\" | \"descending\" | \"other\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChange?: React.FormEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; field: (string & {}) | keyof ", { "pluginId": "savedObjectsManagement", "scope": "public", diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 23557fc411290..526ab50e91670 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 6897592f425e0..505f2a42dc503 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 8c56962b7c305..1ef30026b02e6 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 71ef6d38da933..d3e548f519309 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index a15136ea7f498..82924478cc916 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 8ca5b81c59f8f..b7b7e30361372 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index b2d7f3c70eb5f..005133426198a 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index f25cc8d4489c4..2b59497a340fd 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 88db6e2eb1654..02183745d657e 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 0a7b220de59a4..9d2931bad5e60 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index e8de402286cf8..39f5d7c1ae7b2 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 43ca29ada0f11..a9bc92d8a42e0 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 66ed098cde9f0..be729d6bc2ecf 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 827d79c2f5d7f..5060499f75c43 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index ca338b001ca0f..860ecb737b655 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index d6a5b2b000bfe..8949000fbd29f 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 185200da6bbc2..5e94c6b49e610 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 1c864b995e362..a19d535900d1f 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 7ec642c1e2a11..1d97c165c128a 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 341a5c04a2475..7623f52a7f706 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index c156875e9767e..47c6749027461 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 7f31cca1dc00c..f169e72c7236e 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index a1a76a06abbf6..cc5da08f265c9 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 3221b09707fbc..5f66671a8e6ee 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index e33ab088de1fa..7cc0b4f939a2c 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 676e4b14f9853..0f60b4e9df3a7 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 2c431f2fcfa08..a521051843765 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 4313f21e57b4b..a9a3f8bb2ca79 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index bcf8286f1446c..22f36ce73aeea 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 392482110ff47..79040e0c7cdd2 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 1febebe9560ec..284a2037ab90b 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index cecc3bb05de6b..6fd75ea172182 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 1ada977d7e7af..0be33385141aa 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index f2256ab7fd81e..2c3d8f2e3aeb1 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 3c1401d8d3de5..c9cbbb1faa746 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 4640ce35dfb25..aa93bc6b4f587 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 8d47eb98e7a75..70d76d4c300bb 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 6101f057caae5..0b2176aad94b4 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 88f0a7692d9a9..4312898bd792a 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 8ac4af4a94429..5f30340988ad6 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index fcbccce77a9bb..9f1265bde99de 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 8843ba95a0c41..fae5f15be6a53 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 2106f2a20f716..ed906cba8ff0f 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2023-02-24 +date: 2023-02-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/examples/files_example/public/plugin.ts b/examples/files_example/public/plugin.ts index ba0b1dfd54378..b36928e5f5566 100644 --- a/examples/files_example/public/plugin.ts +++ b/examples/files_example/public/plugin.ts @@ -18,7 +18,10 @@ export class FilesExamplePlugin core: CoreSetup, { files, developerExamples }: FilesExamplePluginsSetup ) { - files.registerFileKind(exampleFileKind); + files.registerFileKind({ + id: exampleFileKind.id, + allowedMimeTypes: exampleFileKind.allowedMimeTypes, + }); developerExamples.register({ appId: PLUGIN_ID, diff --git a/package.json b/package.json index 150f5825385be..025ea7e0a9039 100644 --- a/package.json +++ b/package.json @@ -1312,7 +1312,7 @@ "cssnano": "^5.1.12", "cssnano-preset-default": "^5.2.12", "csstype": "^3.0.2", - "cypress": "^12.5.1", + "cypress": "^12.6.0", "cypress-axe": "^1.3.0", "cypress-file-upload": "^5.0.8", "cypress-multi-reporters": "^1.6.2", diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/header.test.tsx.snap b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/header.test.tsx.snap index 34a68939dfb56..d86194ac7dbaf 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/header.test.tsx.snap +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/header.test.tsx.snap @@ -1,188 +1,208 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Header renders 1`] = ` -
+Array [
, +
+ -
-
-
-
-
+ class="euiHeaderSection euiHeaderSection--dontGrow euiHeaderSection--left" + > +
+
+
+
- + +
+
-
-
-
- + +
-
- -
+ + test + + + +
+ class="euiHeaderSectionItem" + > +
+
-
-
+
, +] `; diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/screen_reader_a11y.test.tsx.snap b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/screen_reader_a11y.test.tsx.snap new file mode 100644 index 0000000000000..f10087a2eb2e0 --- /dev/null +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/screen_reader_a11y.test.tsx.snap @@ -0,0 +1,317 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ScreenReaderRouteAnnouncements renders 1`] = ` + + + +
+ + + , + ], + }, + } + } + isStringTag={true} + serialized={ + Object { + "map": undefined, + "name": "hus3oj-euiScreenReaderOnly", + "next": undefined, + "styles": "; + // Take the element out of the layout + position: absolute; + // Keep it vertically inline + inset-block-start: auto; + // Chrome requires a left value, and Selenium (used by Kibana's FTR) requires an off-screen position for its .getVisibleText() to not register SR-only text + inset-inline-start: -10000px; + // The element must have a size (for some screen readers) + + inline-size: 1px; + block-size: 1px; + + // But reduce the visible size to nothing + clip: rect(0 0 0 0); + clip-path: inset(50%); + // And ensure no overflows occur + overflow: hidden; + // Chrome requires the negative margin to not cause overflows of parent containers + margin: -1px; +;label:euiScreenReaderOnly;;;;", + "toString": [Function], + } + } + /> +
+ +
+ + + +`; diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/header.tsx b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/header.tsx index 66297bf9a9b86..227a94a208ca3 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/header.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/header.tsx @@ -46,6 +46,7 @@ import { HeaderActionMenu } from './header_action_menu'; import { HeaderExtension } from './header_extension'; import { HeaderTopBanner } from './header_top_banner'; import { HeaderMenuButton } from './header_menu_button'; +import { ScreenReaderRouteAnnouncements } from './screen_reader_a11y'; export interface HeaderProps { kibanaVersion: string; @@ -108,6 +109,12 @@ export function Header({ return ( <> + +
diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/screen_reader_a11y.test.tsx b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/screen_reader_a11y.test.tsx new file mode 100644 index 0000000000000..3dfc25c93c25a --- /dev/null +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/screen_reader_a11y.test.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { BehaviorSubject } from 'rxjs'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { ScreenReaderRouteAnnouncements } from './screen_reader_a11y'; +import { mount } from 'enzyme'; + +describe('ScreenReaderRouteAnnouncements', () => { + it('renders', () => { + const component = mountWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); + + it('does not set the focusOnRegionOnTextChange for canvas or discover', () => { + const noFocusComponentCanvas = mount( + + ); + const noFocusComponentDiscover = mount( + + ); + + expect( + noFocusComponentCanvas + .debug() + .includes('') + ).toBeTruthy(); + + expect( + noFocusComponentDiscover + .debug() + .includes('') + ).toBeTruthy(); + }); + + it('sets the focusOnRegionOnTextChange to true for other apps', () => { + const noFocusComponent = mount( + + ); + + expect( + noFocusComponent.debug().includes('') + ).toBeTruthy(); + }); +}); diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/screen_reader_a11y.tsx b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/screen_reader_a11y.tsx new file mode 100644 index 0000000000000..811da52341417 --- /dev/null +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/screen_reader_a11y.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useState, useEffect } from 'react'; +import useObservable from 'react-use/lib/useObservable'; +import { EuiScreenReaderLive } from '@elastic/eui'; + +import type { InternalApplicationStart } from '@kbn/core-application-browser-internal'; +import type { HeaderProps } from './header'; + +const DEFAULT_BRAND = 'Elastic'; // This may need to be DRYed out with https://github.com/elastic/kibana/blob/main/packages/core/rendering/core-rendering-server-internal/src/views/template.tsx#L34 +const SEPARATOR = ' - '; + +export const ScreenReaderRouteAnnouncements: FC<{ + breadcrumbs$: HeaderProps['breadcrumbs$']; + customBranding$: HeaderProps['customBranding$']; + appId$: InternalApplicationStart['currentAppId$']; +}> = ({ breadcrumbs$, customBranding$, appId$ }) => { + const [routeTitle, setRouteTitle] = useState(''); + const branding = useObservable(customBranding$)?.pageTitle || DEFAULT_BRAND; + const breadcrumbs = useObservable(breadcrumbs$, []); + + useEffect(() => { + if (breadcrumbs.length) { + const breadcrumbText: string[] = []; + + // Reverse the breadcrumb title order and ensure we only pick up valid strings + [...breadcrumbs].reverse().forEach((breadcrumb) => { + if (typeof breadcrumb.text === 'string') breadcrumbText.push(breadcrumb.text); + }); + breadcrumbText.push(branding); + + setRouteTitle(breadcrumbText.join(SEPARATOR)); + } else { + // Don't announce anything during loading states + setRouteTitle(''); + } + }, [breadcrumbs, branding]); + + // 1. Canvas dynamically updates breadcrumbs *and* page title/history on every name onChange, + // which leads to focus fighting if this is enabled + // 2. Discover has custom h1 focus behavior on route change, which should probably + // be removed in favor of this for a more consistent SR experience + const appId = useObservable(appId$); + const disableFocusForApps = ['canvas', 'discover']; + const focusRegionOnTextChange = !disableFocusForApps.includes(appId || ''); + + return ( + + {routeTitle} + + ); +}; diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/error_toast.tsx b/packages/core/notifications/core-notifications-browser-internal/src/toasts/error_toast.tsx index fb8b9305d817c..b1c21064d3c91 100644 --- a/packages/core/notifications/core-notifications-browser-internal/src/toasts/error_toast.tsx +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/error_toast.tsx @@ -74,7 +74,7 @@ function showErrorDialog({ {title} - + {text && ( diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/toasts_api.tsx b/packages/core/notifications/core-notifications-browser-internal/src/toasts/toasts_api.tsx index 43e95b68ade20..2b2de9f945c74 100644 --- a/packages/core/notifications/core-notifications-browser-internal/src/toasts/toasts_api.tsx +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/toasts_api.tsx @@ -150,7 +150,7 @@ export class ToastsApi implements IToasts { public addDanger(toastOrTitle: ToastInput, options?: ToastOptions) { return this.add({ color: 'danger', - iconType: 'alert', + iconType: 'error', toastLifeTimeMs: this.uiSettings.get('notifications:lifetime:warning'), ...normalizeToast(toastOrTitle), ...options, @@ -168,7 +168,7 @@ export class ToastsApi implements IToasts { const message = options.toastMessage || error.message; return this.add({ color: 'danger', - iconType: 'alert', + iconType: 'error', toastLifeTimeMs: this.uiSettings.get('notifications:lifetime:error'), text: mountReactNode( > = [ + cspConfig, + deprecationConfig, + elasticsearchConfig, + elasticApmConfig, + executionContextConfig, + externalUrlConfig, + httpConfig, + i18nConfig, + loggingConfig, + nodeConfig, + opsConfig, + pathConfig, + pidConfig, + pluginsConfig, + savedObjectsConfig, + savedObjectsMigrationConfig, + statusConfig, + uiSettingsConfig, + ]; + + configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider); + for (const descriptor of configDescriptors) { + if (descriptor.deprecations) { + configService.addDeprecationProvider(descriptor.path, descriptor.deprecations); + } + configService.setSchema(descriptor.path, descriptor.schema); + } +} diff --git a/packages/core/root/core-root-server-internal/src/server.ts b/packages/core/root/core-root-server-internal/src/server.ts index d7580f19526d8..8c8d636d795e9 100644 --- a/packages/core/root/core-root-server-internal/src/server.ts +++ b/packages/core/root/core-root-server-internal/src/server.ts @@ -7,57 +7,30 @@ */ import apm from 'elastic-apm-node'; -import { config as pathConfig } from '@kbn/utils'; import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; import type { Logger, LoggerFactory } from '@kbn/logging'; import { ConfigService, Env, RawConfigurationProvider } from '@kbn/config'; -import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal'; import { DocLinksService } from '@kbn/core-doc-links-server-internal'; -import { - LoggingService, - ILoggingSystem, - config as loggingConfig, -} from '@kbn/core-logging-server-internal'; -import { - coreDeprecationProvider, - ensureValidConfiguration, -} from '@kbn/core-config-server-internal'; -import { NodeService, nodeConfig } from '@kbn/core-node-server-internal'; +import { LoggingService, ILoggingSystem } from '@kbn/core-logging-server-internal'; +import { ensureValidConfiguration } from '@kbn/core-config-server-internal'; +import { NodeService } from '@kbn/core-node-server-internal'; import { AnalyticsService } from '@kbn/core-analytics-server-internal'; import type { AnalyticsServiceSetup, AnalyticsServiceStart } from '@kbn/core-analytics-server'; -import { EnvironmentService, pidConfig } from '@kbn/core-environment-server-internal'; -import { - ExecutionContextService, - executionContextConfig, -} from '@kbn/core-execution-context-server-internal'; +import { EnvironmentService } from '@kbn/core-environment-server-internal'; +import { ExecutionContextService } from '@kbn/core-execution-context-server-internal'; import { PrebootService } from '@kbn/core-preboot-server-internal'; import { ContextService } from '@kbn/core-http-context-server-internal'; -import { - HttpService, - config as httpConfig, - cspConfig, - externalUrlConfig, -} from '@kbn/core-http-server-internal'; -import { - ElasticsearchService, - config as elasticsearchConfig, -} from '@kbn/core-elasticsearch-server-internal'; -import { MetricsService, opsConfig } from '@kbn/core-metrics-server-internal'; +import { HttpService } from '@kbn/core-http-server-internal'; +import { ElasticsearchService } from '@kbn/core-elasticsearch-server-internal'; +import { MetricsService } from '@kbn/core-metrics-server-internal'; import { CapabilitiesService } from '@kbn/core-capabilities-server-internal'; import type { SavedObjectsServiceStart } from '@kbn/core-saved-objects-server'; -import { - savedObjectsConfig, - savedObjectsMigrationConfig, -} from '@kbn/core-saved-objects-base-server-internal'; import { SavedObjectsService } from '@kbn/core-saved-objects-server-internal'; -import { I18nService, config as i18nConfig } from '@kbn/core-i18n-server-internal'; -import { - DeprecationsService, - config as deprecationConfig, -} from '@kbn/core-deprecations-server-internal'; +import { I18nService } from '@kbn/core-i18n-server-internal'; +import { DeprecationsService } from '@kbn/core-deprecations-server-internal'; import { CoreUsageDataService } from '@kbn/core-usage-data-server-internal'; -import { StatusService, statusConfig } from '@kbn/core-status-server-internal'; -import { UiSettingsService, uiSettingsConfig } from '@kbn/core-ui-settings-server-internal'; +import { StatusService } from '@kbn/core-status-server-internal'; +import { UiSettingsService } from '@kbn/core-ui-settings-server-internal'; import { CustomBrandingService } from '@kbn/core-custom-branding-server-internal'; import { CoreRouteHandlerContext, @@ -75,16 +48,11 @@ import type { InternalCoreSetup, InternalCoreStart, } from '@kbn/core-lifecycle-server-internal'; -import { - DiscoveredPlugins, - PluginsService, - config as pluginsConfig, -} from '@kbn/core-plugins-server-internal'; +import { DiscoveredPlugins, PluginsService } from '@kbn/core-plugins-server-internal'; import { CoreAppsService } from '@kbn/core-apps-server-internal'; -import { elasticApmConfig } from './root/elastic_config'; +import { registerServiceConfig } from './register_service_config'; const coreId = Symbol('core'); -const rootConfigPath = ''; const KIBANA_STARTED_EVENT = 'kibana_started'; /** @internal */ @@ -465,34 +433,7 @@ export class Server { } public setupCoreConfig() { - const configDescriptors: Array> = [ - cspConfig, - deprecationConfig, - elasticsearchConfig, - elasticApmConfig, - executionContextConfig, - externalUrlConfig, - httpConfig, - i18nConfig, - loggingConfig, - nodeConfig, - opsConfig, - pathConfig, - pidConfig, - pluginsConfig, - savedObjectsConfig, - savedObjectsMigrationConfig, - statusConfig, - uiSettingsConfig, - ]; - - this.configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider); - for (const descriptor of configDescriptors) { - if (descriptor.deprecations) { - this.configService.addDeprecationProvider(descriptor.path, descriptor.deprecations); - } - this.configService.setSchema(descriptor.path, descriptor.schema); - } + registerServiceConfig(this.configService); } /** diff --git a/packages/core/saved-objects/core-saved-objects-base-server-internal/src/saved_objects_config.ts b/packages/core/saved-objects/core-saved-objects-base-server-internal/src/saved_objects_config.ts index 22980bd8e88e7..c4d48d66a6a06 100644 --- a/packages/core/saved-objects/core-saved-objects-base-server-internal/src/saved_objects_config.ts +++ b/packages/core/saved-objects/core-saved-objects-base-server-internal/src/saved_objects_config.ts @@ -11,6 +11,9 @@ import { schema, TypeOf } from '@kbn/config-schema'; import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal'; const migrationSchema = schema.object({ + algorithm: schema.oneOf([schema.literal('v2'), schema.literal('zdt')], { + defaultValue: 'v2', + }), batchSize: schema.number({ defaultValue: 1_000 }), maxBatchSizeBytes: schema.byteSize({ defaultValue: '100mb' }), // 100mb is the default http.max_content_length Elasticsearch config value discardUnknownObjects: schema.maybe( diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts index 21fbd6f8b5329..9a4a728184388 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts @@ -6,10 +6,14 @@ * Side Public License, v 1. */ -export { DocumentMigrator, KibanaMigrator, buildActiveMappings, mergeTypes } from './src'; +export { DocumentMigrator, KibanaMigrator, buildActiveMappings, buildTypesMappings } from './src'; export type { KibanaMigratorOptions } from './src'; export { getAggregatedTypesDocuments } from './src/actions/check_for_unknown_docs'; -export { addExcludedTypesToBoolQuery } from './src/model/helpers'; +export { + addExcludedTypesToBoolQuery, + createBulkIndexOperationTuple, + createBulkDeleteOperationBody, +} from './src/model/helpers'; // these are only used for integration tests export { diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/README.md b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/README.md index 8655c3e9c2222..6ae7f7fb09c06 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/README.md +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/README.md @@ -369,9 +369,9 @@ completed this step: - temp index has a write block - temp index is not found ### New control state -1. If `currentBatch` is the last batch in `transformedDocBatches` +1. If `currentBatch` is the last batch in `bulkOperationBatches` → `REINDEX_SOURCE_TO_TEMP_READ` -2. If there are more batches left in `transformedDocBatches` +2. If there are more batches left in `bulkOperationBatches` → `REINDEX_SOURCE_TO_TEMP_INDEX_BULK` ## REINDEX_SOURCE_TO_TEMP_CLOSE_PIT diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap index 6973b0b8a7081..d4ee0d73e94a6 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap @@ -18,6 +18,9 @@ Object { "duration": 0, "state": Object { "batchSize": 1000, + "bulkOperationBatches": Array [ + Array [], + ], "controlState": "LEGACY_REINDEX", "currentAlias": ".my-so-index", "discardCorruptObjects": false, @@ -126,22 +129,6 @@ Object { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, @@ -190,7 +177,6 @@ Object { }, }, }, - "transformedDocBatches": Array [], "versionAlias": ".my-so-index_7.11.0", "versionIndex": ".my-so-index_7.11.0_001", "waitForMigrationCompletion": false, @@ -214,6 +200,9 @@ Object { "duration": 0, "state": Object { "batchSize": 1000, + "bulkOperationBatches": Array [ + Array [], + ], "controlState": "LEGACY_DELETE", "currentAlias": ".my-so-index", "discardCorruptObjects": false, @@ -322,22 +311,6 @@ Object { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, @@ -390,7 +363,6 @@ Object { }, }, }, - "transformedDocBatches": Array [], "versionAlias": ".my-so-index_7.11.0", "versionIndex": ".my-so-index_7.11.0_001", "waitForMigrationCompletion": false, @@ -414,6 +386,9 @@ Object { "duration": 0, "state": Object { "batchSize": 1000, + "bulkOperationBatches": Array [ + Array [], + ], "controlState": "LEGACY_DELETE", "currentAlias": ".my-so-index", "discardCorruptObjects": false, @@ -522,22 +497,6 @@ Object { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, @@ -594,7 +553,6 @@ Object { }, }, }, - "transformedDocBatches": Array [], "versionAlias": ".my-so-index_7.11.0", "versionIndex": ".my-so-index_7.11.0_001", "waitForMigrationCompletion": false, @@ -618,6 +576,9 @@ Object { "duration": 0, "state": Object { "batchSize": 1000, + "bulkOperationBatches": Array [ + Array [], + ], "controlState": "DONE", "currentAlias": ".my-so-index", "discardCorruptObjects": false, @@ -726,22 +687,6 @@ Object { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, @@ -802,7 +747,6 @@ Object { }, }, }, - "transformedDocBatches": Array [], "versionAlias": ".my-so-index_7.11.0", "versionIndex": ".my-so-index_7.11.0_001", "waitForMigrationCompletion": false, @@ -864,6 +808,15 @@ Object { "duration": 0, "state": Object { "batchSize": 1000, + "bulkOperationBatches": Array [ + Array [ + Object { + "index": Object { + "_id": "1234", + }, + }, + ], + ], "controlState": "LEGACY_DELETE", "currentAlias": ".my-so-index", "discardCorruptObjects": false, @@ -972,22 +925,6 @@ Object { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, @@ -1041,13 +978,6 @@ Object { }, }, }, - "transformedDocBatches": Array [ - Array [ - Object { - "_id": "1234", - }, - ], - ], "versionAlias": ".my-so-index_7.11.0", "versionIndex": ".my-so-index_7.11.0_001", "waitForMigrationCompletion": false, @@ -1071,6 +1001,15 @@ Object { "duration": 0, "state": Object { "batchSize": 1000, + "bulkOperationBatches": Array [ + Array [ + Object { + "index": Object { + "_id": "1234", + }, + }, + ], + ], "controlState": "FATAL", "currentAlias": ".my-so-index", "discardCorruptObjects": false, @@ -1179,22 +1118,6 @@ Object { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, @@ -1252,13 +1175,6 @@ Object { }, }, }, - "transformedDocBatches": Array [ - Array [ - Object { - "_id": "1234", - }, - ], - ], "versionAlias": ".my-so-index_7.11.0", "versionIndex": ".my-so-index_7.11.0_001", "waitForMigrationCompletion": false, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.test.ts index 06b5dd762cffc..ac1daf3c8761f 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.test.ts @@ -40,7 +40,7 @@ describe('bulkOverwriteTransformedDocuments', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'new_index', - transformedDocs: [], + operations: [], refresh: 'wait_for', }); @@ -74,7 +74,7 @@ describe('bulkOverwriteTransformedDocuments', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'new_index', - transformedDocs: [], + operations: [], refresh: 'wait_for', }); @@ -99,7 +99,7 @@ describe('bulkOverwriteTransformedDocuments', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'new_index', - transformedDocs: [], + operations: [], refresh: 'wait_for', }); try { @@ -140,7 +140,7 @@ describe('bulkOverwriteTransformedDocuments', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'new_index', - transformedDocs: [], + operations: [], refresh: 'wait_for', }); @@ -193,7 +193,7 @@ describe('bulkOverwriteTransformedDocuments', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'new_index', - transformedDocs: [], + operations: [], refresh: 'wait_for', }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.ts index 7a6e8b2d9a5b5..716683c1938fb 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/bulk_overwrite_transformed_documents.ts @@ -11,7 +11,6 @@ import * as TaskEither from 'fp-ts/lib/TaskEither'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { errors as esErrors } from '@elastic/elasticsearch'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; import { catchRetryableEsClientErrors, type RetryableEsClientError, @@ -19,33 +18,13 @@ import { import { isWriteBlockException, isIndexNotFoundException } from './es_errors'; import { WAIT_FOR_ALL_SHARDS_TO_BE_ACTIVE } from './constants'; import type { TargetIndexHadWriteBlock, RequestEntityTooLargeException, IndexNotFound } from '.'; - -/** - * Given a document and index, creates a valid body for the Bulk API. - */ -export const createBulkOperationBody = (doc: SavedObjectsRawDoc, index: string) => { - return [ - { - index: { - _index: index, - _id: doc._id, - // overwrite existing documents - op_type: 'index', - // use optimistic concurrency control to ensure that outdated - // documents are only overwritten once with the latest version - if_seq_no: doc._seq_no, - if_primary_term: doc._primary_term, - }, - }, - doc._source, - ]; -}; +import type { BulkOperation } from '../model/create_batches'; /** @internal */ export interface BulkOverwriteTransformedDocumentsParams { client: ElasticsearchClient; index: string; - transformedDocs: SavedObjectsRawDoc[]; + operations: BulkOperation[]; refresh?: estypes.Refresh; } @@ -57,7 +36,7 @@ export const bulkOverwriteTransformedDocuments = ({ client, index, - transformedDocs, + operations, refresh = false, }: BulkOverwriteTransformedDocumentsParams): TaskEither.TaskEither< | RetryableEsClientError @@ -67,10 +46,6 @@ export const bulkOverwriteTransformedDocuments = 'bulk_index_succeeded' > => () => { - const body = transformedDocs.flatMap((doc) => { - return createBulkOperationBody(doc, index); - }); - return client .bulk({ // Because we only add aliases in the MARK_VERSION_INDEX_READY step we @@ -80,11 +55,13 @@ export const bulkOverwriteTransformedDocuments = // mappings. Such tampering could lead to many other problems and is // probably unlikely so for now we'll accept this risk and wait till // system indices puts in place a hard control. + index, require_alias: false, wait_for_active_shards: WAIT_FOR_ALL_SHARDS_TO_BE_ACTIVE, refresh, filter_path: ['items.*.error'], - body, + // we need to unwrap the existing BulkIndexOperationTuple's + operations: operations.flat(), }) .then((res) => { // Filter out version_conflict_engine_exception since these just mean diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.test.ts index 95a9a33831d09..da3c11686ec93 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.test.ts @@ -28,7 +28,7 @@ describe('calculateExcludeFilters', () => { expect(hook2).toHaveBeenCalledWith({ readonlyEsClient: { search: expect.any(Function) } }); expect(Either.isRight(result)).toBe(true); expect((result as Either.Right).right).toEqual({ - mustNotClauses: [ + filterClauses: [ { bool: { must: { term: { fieldA: '123' } } } }, { bool: { must: { term: { fieldB: 'abc' } } } }, ], @@ -49,7 +49,7 @@ describe('calculateExcludeFilters', () => { expect(Either.isRight(result)).toBe(true); expect((result as Either.Right).right).toEqual({ - mustNotClauses: [{ bool: { must: { term: { fieldB: 'abc' } } } }], + filterClauses: [{ bool: { must: { term: { fieldB: 'abc' } } } }], errorsByType: { type1: error }, }); }); @@ -91,7 +91,7 @@ describe('calculateExcludeFilters', () => { expect(Either.isRight(result)).toBe(true); expect((result as Either.Right).right).toEqual({ - mustNotClauses: [{ bool: { must: { term: { fieldB: 'abc' } } } }], + filterClauses: [{ bool: { must: { term: { fieldB: 'abc' } } } }], errorsByType: expect.any(Object), }); expect((result as Either.Right).right.errorsByType.type1.toString()).toMatchInlineSnapshot( diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.ts index d0cf8f85fc497..30cc39d0a8fba 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/calculate_exclude_filters.ts @@ -23,7 +23,7 @@ export interface CalculateExcludeFiltersParams { export interface CalculatedExcludeFilter { /** Array with all the clauses that must be bool.must_not'ed */ - mustNotClauses: QueryDslQueryContainer[]; + filterClauses: QueryDslQueryContainer[]; /** Any errors that were encountered during filter calculation, keyed by the type name */ errorsByType: Record; } @@ -91,17 +91,17 @@ export const calculateExcludeFilters = } const errorsByType: Array<[string, Error]> = []; - const mustNotClauses: QueryDslQueryContainer[] = []; + const filterClauses: QueryDslQueryContainer[] = []; // Loop through all results and collect successes and errors results.forEach((r) => Either.isRight(r) - ? mustNotClauses.push(r.right) + ? filterClauses.push(r.right) : Either.isLeft(r) && errorsByType.push([r.left.soType, r.left.error as Error]) ); return Either.right({ - mustNotClauses, + filterClauses, errorsByType: Object.fromEntries(errorsByType), }); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_for_unknown_docs.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_for_unknown_docs.ts index 74dc39bc6fcd4..e483a16c270ff 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_for_unknown_docs.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_for_unknown_docs.ts @@ -116,7 +116,7 @@ export const checkForUnknownDocs = RetryableEsClientError, UnknownDocsFound | {} > => - async () => { + () => { const excludeQuery = addExcludedTypesToBoolQuery(knownTypes, excludeOnUpgradeQuery.bool); return getAggregatedTypesDocuments(client, indexName, excludeQuery) .then((unknownDocs) => { diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.mocks.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.mocks.ts new file mode 100644 index 0000000000000..1b0e0a49e5062 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.mocks.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; + +export const emptyResponseClientMock = elasticsearchClientMock.createInternalClient( + Promise.resolve({ + took: 0, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 0, + relation: 'eq', + }, + max_score: null, + hits: [], + }, + }) +); + +export const initialExcludeOnUpgradeQueryMock = { + bool: { + must_not: [ + { + term: { + type: 'apm-services-telemetry', + }, + }, + { + term: { + type: 'application_usage_transactional', + }, + }, + { + term: { + type: 'background-session', + }, + }, + { + term: { + type: 'cases-sub-case', + }, + }, + { + term: { + type: 'csp_rule', + }, + }, + { + term: { + type: 'file-upload-telemetry', + }, + }, + { + term: { + type: 'fleet-agent-actions', + }, + }, + { + term: { + type: 'fleet-agent-events', + }, + }, + { + term: { + type: 'fleet-agents', + }, + }, + { + term: { + type: 'fleet-enrollment-api-keys', + }, + }, + { + term: { + type: 'guided-setup-state', + }, + }, + { + term: { + type: 'maps-telemetry', + }, + }, + { + term: { + type: 'ml-telemetry', + }, + }, + { + term: { + type: 'osquery-usage-metric', + }, + }, + { + term: { + type: 'server', + }, + }, + { + term: { + type: 'siem-detection-engine-rule-execution-info', + }, + }, + { + term: { + type: 'siem-detection-engine-rule-status', + }, + }, + { + term: { + type: 'timelion-sheet', + }, + }, + { + term: { + type: 'tsvb-validation-telemetry', + }, + }, + { + term: { + type: 'ui-counter', + }, + }, + ], + }, +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.test.ts new file mode 100644 index 0000000000000..af8fb8696d728 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.test.ts @@ -0,0 +1,276 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import { checkForUnknownDocs, type DocumentIdAndType } from './check_for_unknown_docs'; +import { cleanupUnknownAndExcluded } from './cleanup_unknown_and_excluded'; +import { calculateExcludeFilters } from './calculate_exclude_filters'; +import { deleteByQuery } from './delete_by_query'; +import { + emptyResponseClientMock, + initialExcludeOnUpgradeQueryMock, +} from './cleanup_unknown_and_excluded.mocks'; + +jest.mock('./check_for_unknown_docs'); +jest.mock('./calculate_exclude_filters'); +jest.mock('./delete_by_query'); + +const mockCheckForUnknownDocs = checkForUnknownDocs as jest.MockedFunction< + typeof checkForUnknownDocs +>; + +const mockCalculateExcludeFilters = calculateExcludeFilters as jest.MockedFunction< + typeof calculateExcludeFilters +>; + +const mockDeleteByQuery = deleteByQuery as jest.MockedFunction; + +describe('cleanupUnknownAndExcluded', () => { + const unknownDocs: DocumentIdAndType[] = [ + { id: 'dashboard:12345', type: 'dashboard' }, + { id: 'dashboard:67890', type: 'dashboard' }, + ]; + + const excludeFromUpgradeFilterHooks = { + 'search-session': async () => { + return { + bool: { + must: [ + { term: { type: 'search-session' } }, + { match: { 'search-session.persisted': false } }, + ], + }, + }; + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls `Actions.checkForUnknownDocs()` with the correct params', async () => { + mockCheckForUnknownDocs.mockReturnValueOnce(async () => Either.right({})); + mockCalculateExcludeFilters.mockReturnValueOnce(async () => + Either.right({ + filterClauses: [], + errorsByType: {}, + }) + ); + mockDeleteByQuery.mockReturnValueOnce(async () => + Either.right({ + taskId: '1234', + }) + ); + + const task = cleanupUnknownAndExcluded({ + client: emptyResponseClientMock, // the client will not be called anyway + indexName: '.kibana_8.0.0', + discardUnknownDocs: false, + excludeOnUpgradeQuery: initialExcludeOnUpgradeQueryMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 50, + knownTypes: ['foo', 'bar'], + removedTypes: ['server', 'deprecated'], + }); + + await task(); + + expect(checkForUnknownDocs).toHaveBeenCalledTimes(1); + expect(checkForUnknownDocs).toHaveBeenCalledWith({ + client: emptyResponseClientMock, + indexName: '.kibana_8.0.0', + excludeOnUpgradeQuery: initialExcludeOnUpgradeQueryMock, + knownTypes: ['foo', 'bar'], + }); + }); + + it('fails if there are unknown docs and `discardUnknownDocs === false`', async () => { + mockCheckForUnknownDocs.mockReturnValueOnce(async () => + Either.right({ + type: 'unknown_docs_found', + unknownDocs, + }) + ); + + const task = cleanupUnknownAndExcluded({ + client: emptyResponseClientMock, + indexName: '.kibana_8.0.0', + discardUnknownDocs: false, + excludeOnUpgradeQuery: initialExcludeOnUpgradeQueryMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 50, + knownTypes: ['foo', 'bar'], + removedTypes: ['server', 'deprecated'], + }); + + const result = await task(); + + expect(Either.isLeft(result)).toBe(true); + expect((result as Either.Left).left).toEqual({ + type: 'unknown_docs_found', + unknownDocs, + }); + expect(calculateExcludeFilters).not.toHaveBeenCalled(); + expect(deleteByQuery).not.toHaveBeenCalled(); + }); + + describe('if there are no unknown documents', () => { + it('calls `Actions.calculateExcludeFilters()` with the correct params', async () => { + mockCheckForUnknownDocs.mockReturnValueOnce(async () => Either.right({})); + mockCalculateExcludeFilters.mockReturnValueOnce(async () => + Either.right({ + filterClauses: [], + errorsByType: {}, + }) + ); + mockDeleteByQuery.mockReturnValueOnce(async () => + Either.right({ + taskId: '1234', + }) + ); + const task = cleanupUnknownAndExcluded({ + client: emptyResponseClientMock, + indexName: '.kibana_8.0.0', + discardUnknownDocs: false, + excludeOnUpgradeQuery: initialExcludeOnUpgradeQueryMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 50, + knownTypes: ['foo', 'bar'], + removedTypes: ['server', 'deprecated'], + }); + + await task(); + + expect(calculateExcludeFilters).toHaveBeenCalledTimes(1); + expect(calculateExcludeFilters).toHaveBeenCalledWith({ + client: emptyResponseClientMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 50, + }); + }); + }); + + describe('if there are unknown documents and `discardUnknownDocuments === true`', () => { + it('calls `Actions.calculateExcludeFilters()` with the correct params', async () => { + mockCheckForUnknownDocs.mockReturnValueOnce(async () => + Either.right({ + type: 'unknown_docs_found', + unknownDocs, + }) + ); + mockCalculateExcludeFilters.mockReturnValueOnce(async () => + Either.right({ + filterClauses: [], + errorsByType: {}, + }) + ); + mockDeleteByQuery.mockReturnValueOnce(async () => + Either.right({ + taskId: '1234', + }) + ); + const task = cleanupUnknownAndExcluded({ + client: emptyResponseClientMock, + indexName: '.kibana_8.0.0', + discardUnknownDocs: true, + excludeOnUpgradeQuery: initialExcludeOnUpgradeQueryMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 28, + knownTypes: ['foo', 'bar'], + removedTypes: ['server', 'deprecated'], + }); + + await task(); + + expect(calculateExcludeFilters).toHaveBeenCalledTimes(1); + expect(calculateExcludeFilters).toHaveBeenCalledWith({ + client: emptyResponseClientMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 28, + }); + }); + }); + + it('calls `deleteByQuery` with the correct params', async () => { + mockCheckForUnknownDocs.mockReturnValueOnce(async () => + Either.right({ + type: 'unknown_docs_found', + unknownDocs, + }) + ); + + const filterClauses: QueryDslQueryContainer[] = [ + { + bool: { + must: [ + { term: { type: 'search-session' } }, + { match: { 'search-session.persisted': false } }, + ], + }, + }, + ]; + + const errorsByType = { type1: new Error('an error!') }; + + mockCalculateExcludeFilters.mockReturnValueOnce(async () => + Either.right({ filterClauses, errorsByType }) + ); + mockDeleteByQuery.mockReturnValueOnce(async () => + Either.right({ + taskId: '1234', + }) + ); + const task = cleanupUnknownAndExcluded({ + client: emptyResponseClientMock, + indexName: '.kibana_8.0.0', + discardUnknownDocs: true, + excludeOnUpgradeQuery: initialExcludeOnUpgradeQueryMock, + excludeFromUpgradeFilterHooks, + hookTimeoutMs: 28, + knownTypes: ['foo', 'bar'], + removedTypes: ['server', 'deprecated'], + }); + + const result = await task(); + + expect(deleteByQuery).toHaveBeenCalledTimes(1); + expect(deleteByQuery).toHaveBeenCalledWith({ + client: emptyResponseClientMock, + indexName: '.kibana_8.0.0', + query: { + bool: { + should: [ + // excluded from upgrade hook response + { + bool: { + must: [ + { term: { type: 'search-session' } }, + { match: { 'search-session.persisted': false } }, + ], + }, + }, + { term: { type: 'server' } }, // removed type + { term: { type: 'deprecated' } }, // removed type + { term: { type: 'dashboard' } }, // unknown type + ], + }, + }, + conflicts: 'proceed', + refresh: false, + }); + + expect(Either.isRight(result)).toBe(true); + expect((result as Either.Right).right).toEqual({ + type: 'cleanup_started' as const, + taskId: '1234', + unknownDocs, + errorsByType, + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.ts new file mode 100644 index 0000000000000..d7ceeec014ddc --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/cleanup_unknown_and_excluded.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import * as TaskEither from 'fp-ts/lib/TaskEither'; +import { pipe } from 'fp-ts/lib/function'; +import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { SavedObjectTypeExcludeFromUpgradeFilterHook } from '@kbn/core-saved-objects-server'; +import type { RetryableEsClientError } from './catch_retryable_es_client_errors'; +import { + checkForUnknownDocs, + type DocumentIdAndType, + type UnknownDocsFound, +} from './check_for_unknown_docs'; +import { isTypeof } from '.'; +import { CalculatedExcludeFilter, calculateExcludeFilters } from './calculate_exclude_filters'; +import { deleteByQuery } from './delete_by_query'; + +/** @internal */ +export interface CleanupUnknownAndExcludedParams { + client: ElasticsearchClient; + indexName: string; + discardUnknownDocs: boolean; + excludeOnUpgradeQuery: QueryDslQueryContainer; + excludeFromUpgradeFilterHooks: Record; + hookTimeoutMs?: number; + knownTypes: string[]; + removedTypes: string[]; +} + +/** @internal */ +export interface CleanupStarted { + type: 'cleanup_started'; + /** Sample (1000 types * 100 docs per type) of the unknown documents that have been found */ + unknownDocs: DocumentIdAndType[]; + /** Any errors that were encountered during filter calculation, keyed by the type name */ + errorsByType: Record; + /** the id of the asynchronous delete task */ + taskId: string; +} + +/** + * Cleans up unknown and excluded types from the specified index. + */ +export const cleanupUnknownAndExcluded = ({ + client, + indexName, + discardUnknownDocs, + excludeOnUpgradeQuery, + excludeFromUpgradeFilterHooks, + hookTimeoutMs, + knownTypes, + removedTypes, +}: CleanupUnknownAndExcludedParams): TaskEither.TaskEither< + RetryableEsClientError | UnknownDocsFound, + CleanupStarted +> => { + let unknownDocs: DocumentIdAndType[] = []; + let unknownDocTypes: string[] = []; + let errorsByType: Record = {}; + + return pipe( + // check if there are unknown docs + checkForUnknownDocs({ client, indexName, knownTypes, excludeOnUpgradeQuery }), + + // make sure we are allowed to get rid of them (in case there are some) + TaskEither.chainEitherKW((unknownDocsRes: {} | UnknownDocsFound) => { + if (isTypeof(unknownDocsRes, 'unknown_docs_found')) { + unknownDocs = unknownDocsRes.unknownDocs; + unknownDocTypes = [...new Set(unknownDocs.map(({ type }) => type))]; + if (!discardUnknownDocs) { + return Either.left({ + type: 'unknown_docs_found' as const, + unknownDocs: unknownDocsRes.unknownDocs, + }); + } + } + return Either.right(undefined); + }), + + // calculate exclude filters (we use them to build the query for documents that must be deleted) + TaskEither.chainW( + (): TaskEither.TaskEither => + calculateExcludeFilters({ client, excludeFromUpgradeFilterHooks, hookTimeoutMs }) + ), + + // actively delete unwanted documents + TaskEither.chainW((excludeFiltersRes) => { + errorsByType = excludeFiltersRes.errorsByType; + + // we must delete everything that matches: + // - any of the plugin-defined exclude filters + // - OR any of the unknown types + const deleteQuery: QueryDslQueryContainer = { + bool: { + should: [ + ...excludeFiltersRes.filterClauses, + ...removedTypes.map((type) => ({ term: { type } })), + ...unknownDocTypes.map((type) => ({ term: { type } })), + ], + }, + }; + + return deleteByQuery({ + client, + indexName, + query: deleteQuery, + // we want to delete as many docs as we can in the current attempt + conflicts: 'proceed', + // instead of forcing refresh after each delete attempt, + // we opt for a delayRetry mechanism when conflicts appear, + // letting the periodic refresh kick in + refresh: false, + }); + }), + + // map response output + TaskEither.chainEitherKW((res) => { + return Either.right({ + type: 'cleanup_started' as const, + taskId: res.taskId, + unknownDocs, + errorsByType, + }); + }) + ); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/delete_by_query.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/delete_by_query.test.ts new file mode 100644 index 0000000000000..784edfdc67b6a --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/delete_by_query.test.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; +import { errors as EsErrors } from '@elastic/elasticsearch'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { deleteByQuery } from './delete_by_query'; + +jest.mock('./catch_retryable_es_client_errors'); + +describe('deleteByQuery', () => { + const deleteQuery = { + bool: { + should: ['server', 'deprecated'].map((type) => ({ + term: { + type, + }, + })), + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls catchRetryableEsClientErrors when the promise rejects', async () => { + // Create a mock client that rejects all methods with a 503 status code response. + const retryableError = new EsErrors.ResponseError( + elasticsearchClientMock.createApiResponse({ + statusCode: 503, + body: { error: { type: 'es_type', reason: 'es_reason' } }, + }) + ); + const client = elasticsearchClientMock.createInternalClient( + elasticsearchClientMock.createErrorTransportRequestPromise(retryableError) + ); + + const task = deleteByQuery({ + client, + indexName: '.kibana_8.0.0', + query: deleteQuery, + conflicts: 'proceed', + refresh: true, + }); + try { + await task(); + } catch (e) { + /** ignore */ + } + expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); + }); + + it('calls `client.deleteByQuery` with the correct parameters', async () => { + const client = elasticsearchClientMock.createInternalClient( + Promise.resolve({ hits: { hits: [] } }) + ); + + const task = deleteByQuery({ + client, + indexName: '.kibana_8.0.0', + query: deleteQuery, + conflicts: 'proceed', + refresh: true, + }); + + await task(); + + expect(client.deleteByQuery).toHaveBeenCalledTimes(1); + expect(client.deleteByQuery).toHaveBeenCalledWith({ + index: '.kibana_8.0.0', + query: deleteQuery, + refresh: true, + wait_for_completion: false, + conflicts: 'proceed', + }); + }); + + it('resolves with `Either.right` if the delete task is successfully created', async () => { + const client = elasticsearchClientMock.createInternalClient( + Promise.resolve({ + took: 147, + timed_out: false, + task: 1234, + }) + ); + + const task = deleteByQuery({ + client, + indexName: '.kibana_8.0.0', + query: deleteQuery, + conflicts: 'proceed', + refresh: true, + }); + + const result = await task(); + + expect(Either.isRight(result)).toBe(true); + expect((result as Either.Right).right).toEqual({ taskId: '1234' }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/delete_by_query.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/delete_by_query.ts new file mode 100644 index 0000000000000..f9c426c26696d --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/delete_by_query.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import * as TaskEither from 'fp-ts/lib/TaskEither'; +import type { Conflicts, QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { + catchRetryableEsClientErrors, + type RetryableEsClientError, +} from './catch_retryable_es_client_errors'; + +/** @internal */ +export interface DeleteByQueryParams { + client: ElasticsearchClient; + indexName: string; + query: QueryDslQueryContainer; + conflicts: Conflicts; + refresh?: boolean; +} + +/** @internal */ +export interface DeleteByQueryResponse { + taskId: string; +} + +/** + * Deletes documents matching the provided query + */ +export const deleteByQuery = + ({ + client, + indexName, + query, + conflicts, + refresh = false, + }: DeleteByQueryParams): TaskEither.TaskEither => + () => { + return client + .deleteByQuery({ + index: indexName, + query, + refresh, + conflicts, + wait_for_completion: false, + }) + .then(({ task: taskId }) => { + return Either.right({ taskId: String(taskId!) }); + }) + .catch(catchRetryableEsClientErrors); + }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts index 6b6db29563443..2593ac7867d1e 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts @@ -76,6 +76,10 @@ import type { AliasNotFound, RemoveIndexNotAConcreteIndex } from './update_alias export type { AliasAction, UpdateAliasesParams } from './update_aliases'; export { updateAliases } from './update_aliases'; +export { cleanupUnknownAndExcluded } from './cleanup_unknown_and_excluded'; + +export { waitForDeleteByQueryTask } from './wait_for_delete_by_query_task'; + export type { CreateIndexParams } from './create_index'; export { createIndex } from './create_index'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_delete_by_query_task.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_delete_by_query_task.test.ts new file mode 100644 index 0000000000000..8f9b60cfe02d1 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_delete_by_query_task.test.ts @@ -0,0 +1,199 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import * as TaskEither from 'fp-ts/lib/TaskEither'; +import * as Option from 'fp-ts/lib/Option'; +import { errors as EsErrors, TransportResult } from '@elastic/elasticsearch'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { waitForDeleteByQueryTask } from './wait_for_delete_by_query_task'; +import { waitForTask } from './wait_for_task'; + +jest.mock('./wait_for_task'); + +const mockWaitForTask = waitForTask as jest.MockedFunction; + +describe('waitForDeleteByQueryTask', () => { + const client = elasticsearchClientMock.createInternalClient( + Promise.resolve(elasticsearchClientMock.createApiResponse({})) + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls waitForTask() with the appropriate params', async () => { + // Mock wait for delete finished successfully + mockWaitForTask.mockReturnValueOnce( + TaskEither.right({ + completed: true, + error: Option.none, + failures: Option.none, + description: 'some description', + }) + ); + + const task = waitForDeleteByQueryTask({ + client, + taskId: 'some task id', + timeout: '60s', + }); + + await task(); + + expect(waitForTask).toHaveBeenCalledWith({ + client, + taskId: 'some task id', + timeout: '60s', + }); + }); + + describe('when waitForTask() method rejects with a task completion timeout error', () => { + it('catches the error and returns the appropriate Left response', async () => { + // Mock task completion error + const error = createError({ + body: { error: { type: 'timeout_exception', reason: 'es_reason' } }, + }); + + mockWaitForTask.mockReturnValueOnce( + TaskEither.left({ + type: 'wait_for_task_completion_timeout' as const, + message: '[timeout_exception] es_reason', + error, + }) + ); + + const task = waitForDeleteByQueryTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + const res = await task(); + + expect(res).toEqual( + Either.left({ + type: 'wait_for_task_completion_timeout' as const, + message: '[timeout_exception] es_reason', + error, + }) + ); + }); + }); + + describe('when waitForTask() method rejects with a retryable error', () => { + it('catches the error and returns the appropriate Left response', async () => { + // Mock retryable error + const error = createError({ + statusCode: 503, + body: { error: { type: 'es_type', reason: 'es_reason' } }, + }); + + mockWaitForTask.mockReturnValueOnce( + TaskEither.left({ + type: 'retryable_es_client_error' as const, + message: 'es_type', + error, + }) + ); + + const task = waitForDeleteByQueryTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + const res = await task(); + expect(res).toEqual( + Either.left({ + type: 'retryable_es_client_error' as const, + message: 'es_type', + error, + }) + ); + }); + }); + + describe('when waitForTask() method finishes successfully, but there are failures', () => { + it('returns a Left response, with the list of failures', async () => { + // Mock successful with failures + const failures = ['dashboard:12345 - Failed to delete', 'dashboard:67890 - Failed to delete']; + + mockWaitForTask.mockReturnValueOnce( + TaskEither.right({ + completed: true, + failures: Option.some(failures), + error: Option.none, + }) + ); + + const task = waitForDeleteByQueryTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + const res = await task(); + expect(res).toEqual( + Either.left({ + type: 'cleanup_failed' as const, + failures, + }) + ); + }); + }); + + describe('when waitForTask() method throws an unexpected error', () => { + it('rethrows the error', async () => { + // Mock unexpected 500 Server Error + const error = createError({ + statusCode: 500, + body: { error: { type: 'server_error', reason: 'Something really bad happened' } }, + }); + + mockWaitForTask.mockReturnValueOnce(async () => { + throw error; + }); + + const task = waitForDeleteByQueryTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + expect(task()).rejects.toEqual(error); + }); + }); + + describe('when waitForTask() method finishes successfully without failures', () => { + it('finsihes with a cleanup_successful Right clause', async () => { + // Mock wait for delete finished successfully + mockWaitForTask.mockReturnValueOnce( + TaskEither.right({ + completed: true, + error: Option.none, + failures: Option.none, + description: 'some description', + }) + ); + const task = waitForDeleteByQueryTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + const res = await task(); + + expect(res).toEqual(Either.right({ type: 'cleanup_successful' as const })); + }); + }); +}); + +const createError = (esResponse: Partial) => { + return new EsErrors.ResponseError(elasticsearchClientMock.createApiResponse(esResponse)); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_delete_by_query_task.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_delete_by_query_task.ts new file mode 100644 index 0000000000000..5fae1283b083b --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_delete_by_query_task.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as TaskEither from 'fp-ts/lib/TaskEither'; +import * as Option from 'fp-ts/lib/Option'; +import { flow } from 'fp-ts/lib/function'; +import { waitForTask } from './wait_for_task'; + +/** @internal */ +export interface CleanupErrorResponse { + type: 'cleanup_failed'; + failures: string[]; + versionConflicts?: number; +} + +/** @internal */ +export interface CleanupSuccessfulResponse { + type: 'cleanup_successful'; + deleted?: number; +} + +export const waitForDeleteByQueryTask = flow( + waitForTask, + TaskEither.chainW( + (res): TaskEither.TaskEither => { + if (Option.isSome(res.failures) || res.response?.version_conflicts) { + return TaskEither.left({ + type: 'cleanup_failed' as const, + failures: Option.isSome(res.failures) ? res.failures.value : [], + versionConflicts: res.response?.version_conflicts, + }); + } else if (Option.isSome(res.error)) { + throw new Error( + 'waitForDeleteByQueryTask task failed with the following error:\n' + + JSON.stringify(res.error.value) + ); + } else { + return TaskEither.right({ + type: 'cleanup_successful' as const, + deleted: res.response?.deleted, + }); + } + } + ) +); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_pickup_updated_mappings_task.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_pickup_updated_mappings_task.test.ts index 896a687c1f8d3..66d7689a0b9e4 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_pickup_updated_mappings_task.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_pickup_updated_mappings_task.test.ts @@ -10,32 +10,33 @@ import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors import { errors as EsErrors } from '@elastic/elasticsearch'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { waitForPickupUpdatedMappingsTask } from './wait_for_pickup_updated_mappings_task'; -import { setWriteBlock } from './set_write_block'; -jest.mock('./catch_retryable_es_client_errors'); +jest.mock('./catch_retryable_es_client_errors', () => { + const { catchRetryableEsClientErrors: actualImplementation } = jest.requireActual( + './catch_retryable_es_client_errors' + ); + return { + catchRetryableEsClientErrors: jest.fn(actualImplementation), + }; +}); describe('waitForPickupUpdatedMappingsTask', () => { beforeEach(() => { jest.clearAllMocks(); }); - // Create a mock client that rejects all methods with a 503 status code - // response. - const retryableError = new EsErrors.ResponseError( - elasticsearchClientMock.createApiResponse({ - statusCode: 503, - body: { error: { type: 'es_type', reason: 'es_reason' } }, - }) - ); - const client = elasticsearchClientMock.createInternalClient( - elasticsearchClientMock.createErrorTransportRequestPromise(retryableError) - ); - - const nonRetryableError = new Error('crash'); - const clientWithNonRetryableError = elasticsearchClientMock.createInternalClient( - elasticsearchClientMock.createErrorTransportRequestPromise(nonRetryableError) - ); it('calls catchRetryableEsClientErrors when the promise rejects', async () => { + // Create a mock client that rejects all methods with a 503 status code + // response. + const retryableError = new EsErrors.ResponseError( + elasticsearchClientMock.createApiResponse({ + statusCode: 503, + body: { error: { type: 'es_type', reason: 'es_reason' } }, + }) + ); + const client = elasticsearchClientMock.createInternalClient( + elasticsearchClientMock.createErrorTransportRequestPromise(retryableError) + ); const task = waitForPickupUpdatedMappingsTask({ client, taskId: 'my task id', @@ -50,11 +51,16 @@ describe('waitForPickupUpdatedMappingsTask', () => { expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); }); it('re-throws non retry-able errors', async () => { - const task = setWriteBlock({ - client: clientWithNonRetryableError, - index: 'my_index', + const nonRetryableError = new Error('crash'); + const client = elasticsearchClientMock.createInternalClient( + elasticsearchClientMock.createErrorTransportRequestPromise(nonRetryableError) + ); + + const task = waitForPickupUpdatedMappingsTask({ + client, + taskId: 'my task id', + timeout: '2m', }); - await task(); - expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(nonRetryableError); + expect(task()).rejects.toThrowError(nonRetryableError); }); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.test.ts index 4a5fc20e1fe12..61611dc5afc81 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.test.ts @@ -5,44 +5,113 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { errors as EsErrors } from '@elastic/elasticsearch'; -import { waitForTask } from './wait_for_task'; -import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; -import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; -jest.mock('./catch_retryable_es_client_errors'); +import * as Either from 'fp-ts/lib/Either'; +import { errors as EsErrors, TransportResult } from '@elastic/elasticsearch'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { waitForTask } from './wait_for_task'; describe('waitForTask', () => { beforeEach(() => { jest.clearAllMocks(); }); - // Create a mock client that rejects all methods with a 503 status code - // response. - const retryableError = new EsErrors.ResponseError( - elasticsearchClientMock.createApiResponse({ + it('calls tasks API get() with the correct parameters', async () => { + // Mock client that rejects with a retryable error + const { client } = createErrorClient({ statusCode: 503, body: { error: { type: 'es_type', reason: 'es_reason' } }, - }) - ); - const client = elasticsearchClientMock.createInternalClient( - elasticsearchClientMock.createErrorTransportRequestPromise(retryableError) - ); + }); + + const task = waitForTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + await task(); + expect(client.tasks.get).toHaveBeenCalledTimes(1); + expect(client.tasks.get).toHaveBeenCalledWith({ + task_id: 'my task id', + wait_for_completion: true, + timeout: '60s', + }); + }); + + describe('when tasks API get() method rejects with a task completion timeout error', () => { + it('catches the error and returns the appropriate Left response', async () => { + // Mock client that rejects with a task completion timeout error + const { client, error } = createErrorClient({ + body: { error: { type: 'timeout_exception', reason: 'es_reason' } }, + }); + + const task = waitForTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + const res = await task(); + + expect(res).toEqual( + Either.left({ + type: 'wait_for_task_completion_timeout' as const, + message: '[timeout_exception] es_reason', + error, + }) + ); + }); + }); + + describe('when tasks API get() method rejects with a retryable error', () => { + it('catches the error and returns the appropriate Left response', async () => { + // Mock client that rejects with a 503 status code + const { client, error } = createErrorClient({ + statusCode: 503, + body: { error: { type: 'es_type', reason: 'es_reason' } }, + }); - describe('waitForPickupUpdatedMappingsTask', () => { - it('calls catchRetryableEsClientErrors when the promise rejects', async () => { const task = waitForTask({ client, taskId: 'my task id', timeout: '60s', }); - try { - await task(); - } catch (e) { - /** ignore */ - } - expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); + const res = await task(); + expect(res).toEqual( + Either.left({ + type: 'retryable_es_client_error' as const, + message: 'es_type', + error, + }) + ); + }); + }); + + describe('when tasks API get() method rejects with an unexpected error', () => { + it('rethrows the error', async () => { + // Mock client that rejects with a 500 Server Error + const { client, error } = createErrorClient({ + statusCode: 500, + body: { error: { type: 'server_error', reason: 'Something really bad happened' } }, + }); + + const task = waitForTask({ + client, + taskId: 'my task id', + timeout: '60s', + }); + + expect(task()).rejects.toEqual(error); }); }); }); + +const createErrorClient = (esResponse: Partial) => { + const error = new EsErrors.ResponseError(elasticsearchClientMock.createApiResponse(esResponse)); + const client = elasticsearchClientMock.createInternalClient( + elasticsearchClientMock.createErrorTransportRequestPromise(error) + ); + + return { client, error }; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.ts index 8bb3abaec87db..86389f01727b7 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/wait_for_task.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import * as Option from 'fp-ts/lib/Option'; @@ -22,6 +22,7 @@ export interface WaitForTaskResponse { completed: boolean; failures: Option.Option; description?: string; + response?: estypes.TasksTaskStatus; } /** @@ -90,6 +91,7 @@ export const waitForTask = error: Option.fromNullable(body.error as estypes.ErrorCauseKeys), failures: failures.length > 0 ? Option.some(failures) : Option.none, description: body.task.description, + response: body.response, }); }) .catch(catchWaitForTaskCompletionTimeout) diff --git a/packages/shared-ux/button_toolbar/src/buttons/primary/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/index.ts similarity index 77% rename from packages/shared-ux/button_toolbar/src/buttons/primary/index.ts rename to packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/index.ts index 1d3220b3654aa..962f40b87db02 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/primary/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/index.ts @@ -6,5 +6,4 @@ * Side Public License, v 1. */ -export { PrimaryButton } from './primary'; -export type { Props as PrimaryButtonProps } from './primary'; +export { logActionResponse, logStateTransition, type LogAwareState } from './logs'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts new file mode 100644 index 0000000000000..2f3a1459f594c --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Logger, LogMeta } from '@kbn/logging'; +import { MigrationLog } from '../../types'; + +export interface LogAwareState { + controlState: string; + logs: MigrationLog[]; +} + +interface StateTransitionLogMeta extends LogMeta { + kibana: { + migrations: { + state: LogAwareState; + duration: number; + }; + }; +} + +export const logStateTransition = ( + logger: Logger, + logMessagePrefix: string, + prevState: LogAwareState, + currState: LogAwareState, + tookMs: number +) => { + if (currState.logs.length > prevState.logs.length) { + currState.logs.slice(prevState.logs.length).forEach(({ message, level }) => { + switch (level) { + case 'error': + return logger.error(logMessagePrefix + message); + case 'warning': + return logger.warn(logMessagePrefix + message); + case 'info': + return logger.info(logMessagePrefix + message); + default: + throw new Error(`unexpected log level ${level}`); + } + }); + } + + logger.info( + logMessagePrefix + `${prevState.controlState} -> ${currState.controlState}. took: ${tookMs}ms.` + ); + logger.debug( + logMessagePrefix + `${prevState.controlState} -> ${currState.controlState}. took: ${tookMs}ms.`, + { + kibana: { + migrations: { + state: currState, + duration: tookMs, + }, + }, + } + ); +}; + +export const logActionResponse = ( + logger: Logger, + logMessagePrefix: string, + state: LogAwareState, + res: unknown +) => { + logger.debug(logMessagePrefix + `${state.controlState} RESPONSE`, res as LogMeta); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/build_types_mappings.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/build_types_mappings.ts new file mode 100644 index 0000000000000..6c78ae52550c5 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/build_types_mappings.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; +import type { SavedObjectsTypeMappingDefinitions } from '@kbn/core-saved-objects-base-server-internal'; + +/** + * Merge mappings from all registered saved object types. + */ +export const buildTypesMappings = ( + types: SavedObjectsType[] +): SavedObjectsTypeMappingDefinitions => { + return types.reduce((acc, { name: type, mappings }) => { + const duplicate = acc.hasOwnProperty(type); + if (duplicate) { + throw new Error(`Type ${type} is already defined.`); + } + return { + ...acc, + [type]: mappings, + }; + }, {}); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/index.ts index 81bacea4a0cbd..a113e5e5f77bc 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/index.ts @@ -11,6 +11,8 @@ export type { LogFn } from './migration_logger'; export { excludeUnusedTypesQuery, REMOVED_TYPES } from './unused_types'; export { TransformSavedObjectDocumentError } from './transform_saved_object_document_error'; export { deterministicallyRegenerateObjectId } from './regenerate_object_id'; +export { buildTypesMappings } from './build_types_mappings'; +export { createIndexMap, type IndexMap, type CreateIndexMapOptions } from './build_index_map'; export type { DocumentsTransformFailed, DocumentsTransformSuccess, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts index e506ff40073fc..d4af205bdd829 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts @@ -47,10 +47,6 @@ export const REMOVED_TYPES: string[] = [ 'csp_rule', ].sort(); -// When migrating from the outdated index we use a read query which excludes -// saved objects which are no longer used. These saved objects will still be -// kept in the outdated index for backup purposes, but won't be available in -// the upgraded index. export const excludeUnusedTypesQuery: QueryDslQueryContainer = { bool: { must_not: [ @@ -59,23 +55,6 @@ export const excludeUnusedTypesQuery: QueryDslQueryContainer = { type: typeName, }, })), - // https://github.com/elastic/kibana/issues/96131 - { - bool: { - must: [ - { - match: { - type: 'search-session', - }, - }, - { - match: { - 'search-session.persisted': false, - }, - }, - ], - }, - }, ], }, }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/index.ts index b50f64a26620d..97e62e8657d5e 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -export { KibanaMigrator, mergeTypes } from './kibana_migrator'; +export { KibanaMigrator } from './kibana_migrator'; export type { KibanaMigratorOptions } from './kibana_migrator'; -export { buildActiveMappings } from './core'; +export { buildActiveMappings, buildTypesMappings } from './core'; export { DocumentMigrator } from './document_migrator'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts index 27798706e8fd1..8b6e5e1d7992b 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts @@ -163,22 +163,6 @@ describe('createInitialState', () => { "type": "ui-counter", }, }, - Object { - "bool": Object { - "must": Array [ - Object { - "match": Object { - "type": "search-session", - }, - }, - Object { - "match": Object { - "search-session.persisted": false, - }, - }, - ], - }, - }, ], }, }, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts index 655f164b831cf..f5a462ebcedac 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts @@ -281,6 +281,7 @@ const mockOptions = () => { ]), kibanaIndex: '.my-index', soMigrationsConfig: { + algorithm: 'v2', batchSize: 20, maxBatchSizeBytes: ByteSizeValue.parse('20mb'), pollInterval: 20000, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts index fa0c88629758b..408b277444995 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts @@ -16,7 +16,6 @@ import Semver from 'semver'; import type { Logger } from '@kbn/logging'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; import type { SavedObjectUnsanitizedDoc, SavedObjectsRawDoc, @@ -31,11 +30,12 @@ import { type KibanaMigratorStatus, type MigrationResult, } from '@kbn/core-saved-objects-base-server-internal'; -import { buildActiveMappings } from './core'; +import { buildActiveMappings, buildTypesMappings } from './core'; import { DocumentMigrator, type VersionedTransformer } from './document_migrator'; import { createIndexMap } from './core/build_index_map'; import { runResilientMigrator } from './run_resilient_migrator'; import { migrateRawDocsSafely } from './core/migrate_raw_docs'; +import { runZeroDowntimeMigration } from './zdt'; // ensure plugins don't try to convert SO namespaceTypes after 8.0.0 // see https://github.com/elastic/kibana/issues/147344 @@ -91,7 +91,7 @@ export class KibanaMigrator implements IKibanaMigrator { this.soMigrationsConfig = soMigrationsConfig; this.typeRegistry = typeRegistry; this.serializer = new SavedObjectsSerializer(this.typeRegistry); - this.mappingProperties = mergeTypes(this.typeRegistry.getAllTypes()); + this.mappingProperties = buildTypesMappings(this.typeRegistry.getAllTypes()); this.log = logger; this.kibanaVersion = kibanaVersion; this.documentMigrator = new DocumentMigrator({ @@ -135,6 +135,28 @@ export class KibanaMigrator implements IKibanaMigrator { } private runMigrationsInternal(): Promise { + const migrationAlgorithm = this.soMigrationsConfig.algorithm; + if (migrationAlgorithm === 'zdt') { + return this.runMigrationZdt(); + } else { + return this.runMigrationV2(); + } + } + + private runMigrationZdt(): Promise { + return runZeroDowntimeMigration({ + kibanaIndexPrefix: this.kibanaIndex, + typeRegistry: this.typeRegistry, + logger: this.log, + documentMigrator: this.documentMigrator, + migrationConfig: this.soMigrationsConfig, + docLinks: this.docLinks, + serializer: this.serializer, + elasticsearchClient: this.client, + }); + } + + private runMigrationV2(): Promise { const indexMap = createIndexMap({ kibanaIndexName: this.kibanaIndex, indexMap: this.mappingProperties, @@ -187,20 +209,3 @@ export class KibanaMigrator implements IKibanaMigrator { return this.documentMigrator.migrate(doc); } } - -/** - * Merges savedObjectMappings properties into a single object, verifying that - * no mappings are redefined. - */ -export function mergeTypes(types: SavedObjectsType[]): SavedObjectsTypeMappingDefinitions { - return types.reduce((acc, { name: type, mappings }) => { - const duplicate = acc.hasOwnProperty(type); - if (duplicate) { - throw new Error(`Type ${type} is already defined.`); - } - return { - ...acc, - [type]: mappings, - }; - }, {}); -} diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts index 255a26275b6e8..48a3bad0d0960 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts @@ -17,7 +17,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; import { errors } from '@elastic/elasticsearch'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; -import { AllControlStates, State } from './state'; +import type { AllControlStates, State } from './state'; import { createInitialState } from './initial_state'; import { ByteSizeValue } from '@kbn/config-schema'; @@ -44,6 +44,7 @@ describe('migrationsStateActionMachine', () => { migrationVersionPerType: {}, indexPrefix: '.my-so-index', migrationsConfig: { + algorithm: 'v2', batchSize: 1000, maxBatchSizeBytes: new ByteSizeValue(1e8), pollInterval: 0, @@ -102,7 +103,9 @@ describe('migrationsStateActionMachine', () => { ...initialState, reason: 'the fatal reason', outdatedDocuments: [{ _id: '1234', password: 'sensitive password' }], - transformedDocBatches: [[{ _id: '1234', password: 'sensitive transformed password' }]], + bulkOperationBatches: [ + [[{ index: { _id: '1234' } }, { password: 'sensitive transformed password' }]], + ], } as State, logger: mockLogger.get(), model: transitionModel(['LEGACY_DELETE', 'FATAL']), diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.ts index ef9db961c8112..1b5caf3c4e75d 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.ts @@ -8,72 +8,19 @@ import { errors as EsErrors } from '@elastic/elasticsearch'; import * as Option from 'fp-ts/lib/Option'; -import type { Logger, LogMeta } from '@kbn/logging'; +import type { Logger } from '@kbn/logging'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { getErrorMessage, getRequestDebugMeta, } from '@kbn/core-elasticsearch-client-server-internal'; import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; +import type { BulkOperationContainer } from '@elastic/elasticsearch/lib/api/types'; +import { logActionResponse, logStateTransition } from './common/utils/logs'; import { type Model, type Next, stateActionMachine } from './state_action_machine'; import { cleanup } from './migrations_state_machine_cleanup'; import type { ReindexSourceToTempTransform, ReindexSourceToTempIndexBulk, State } from './state'; - -interface StateTransitionLogMeta extends LogMeta { - kibana: { - migrations: { - state: State; - duration: number; - }; - }; -} - -const logStateTransition = ( - logger: Logger, - logMessagePrefix: string, - prevState: State, - currState: State, - tookMs: number -) => { - if (currState.logs.length > prevState.logs.length) { - currState.logs.slice(prevState.logs.length).forEach(({ message, level }) => { - switch (level) { - case 'error': - return logger.error(logMessagePrefix + message); - case 'warning': - return logger.warn(logMessagePrefix + message); - case 'info': - return logger.info(logMessagePrefix + message); - default: - throw new Error(`unexpected log level ${level}`); - } - }); - } - - logger.info( - logMessagePrefix + `${prevState.controlState} -> ${currState.controlState}. took: ${tookMs}ms.` - ); - logger.debug( - logMessagePrefix + `${prevState.controlState} -> ${currState.controlState}. took: ${tookMs}ms.`, - { - kibana: { - migrations: { - state: currState, - duration: tookMs, - }, - }, - } - ); -}; - -const logActionResponse = ( - logger: Logger, - logMessagePrefix: string, - state: State, - res: unknown -) => { - logger.debug(logMessagePrefix + `${state.controlState} RESPONSE`, res as LogMeta); -}; +import type { BulkOperation } from './model/create_batches'; /** * A specialized migrations-specific state-action machine that: @@ -128,9 +75,9 @@ export async function migrationStateActionMachine({ ), }, ...{ - transformedDocBatches: ( - (newState as ReindexSourceToTempIndexBulk).transformedDocBatches ?? [] - ).map((batches) => batches.map((doc) => ({ _id: doc._id }))) as [SavedObjectsRawDoc[]], + bulkOperationBatches: redactBulkOperationBatches( + (newState as ReindexSourceToTempIndexBulk).bulkOperationBatches ?? [[]] + ), }, }; @@ -212,3 +159,11 @@ export async function migrationStateActionMachine({ } } } + +const redactBulkOperationBatches = ( + bulkOperationBatches: BulkOperation[][] +): BulkOperationContainer[][] => { + return bulkOperationBatches.map((batch) => + batch.map((operation) => (Array.isArray(operation) ? operation[0] : operation)) + ); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_machine_cleanup.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_machine_cleanup.ts index 8b1f93c327857..c3f6016ea9d9b 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_machine_cleanup.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_machine_cleanup.ts @@ -8,10 +8,13 @@ import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import * as Actions from './actions'; -import type { State } from './state'; -export async function cleanup(client: ElasticsearchClient, state?: State) { - if (!state) return; +type CleanableState = { sourceIndexPitId: string } | {}; + +export async function cleanup(client: ElasticsearchClient, state?: CleanableState) { + if (!state) { + return; + } if ('sourceIndexPitId' in state) { await Actions.closePit({ client, pitId: state.sourceIndexPitId })(); } diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.test.ts index ec9afc31f90d1..3ae3b1c7f20d8 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.test.ts @@ -10,8 +10,13 @@ import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; import { createBatches } from './create_batches'; describe('createBatches', () => { - const DOCUMENT_SIZE_BYTES = 128; - const INDEX = '.kibana_version_index'; + const documentToOperation = (document: SavedObjectsRawDoc) => [ + { index: { _id: document._id } }, + document._source, + ]; + + const DOCUMENT_SIZE_BYTES = 77; // 76 + \n + it('returns right one batch if all documents fit in maxBatchSizeBytes', () => { const documents = [ { _id: '', _source: { type: 'dashboard', title: 'my saved object title ¹' } }, @@ -19,8 +24,8 @@ describe('createBatches', () => { { _id: '', _source: { type: 'dashboard', title: 'my saved object title ®' } }, ]; - expect(createBatches(documents, INDEX, DOCUMENT_SIZE_BYTES * 3)).toEqual( - Either.right([documents]) + expect(createBatches({ documents, maxBatchSizeBytes: DOCUMENT_SIZE_BYTES * 3 })).toEqual( + Either.right([documents.map(documentToOperation)]) ); }); it('creates multiple batches with each batch limited to maxBatchSizeBytes', () => { @@ -31,32 +36,36 @@ describe('createBatches', () => { { _id: '', _source: { type: 'dashboard', title: 'my saved object title 44' } }, { _id: '', _source: { type: 'dashboard', title: 'my saved object title 55' } }, ]; - expect(createBatches(documents, INDEX, DOCUMENT_SIZE_BYTES * 2)).toEqual( - Either.right([[documents[0], documents[1]], [documents[2], documents[3]], [documents[4]]]) + expect(createBatches({ documents, maxBatchSizeBytes: DOCUMENT_SIZE_BYTES * 2 })).toEqual( + Either.right([ + documents.slice(0, 2).map(documentToOperation), + documents.slice(2, 4).map(documentToOperation), + documents.slice(4).map(documentToOperation), + ]) ); }); it('creates a single empty batch if there are no documents', () => { const documents = [] as SavedObjectsRawDoc[]; - expect(createBatches(documents, INDEX, 100)).toEqual(Either.right([[]])); + expect(createBatches({ documents, maxBatchSizeBytes: 100 })).toEqual(Either.right([[]])); }); it('throws if any one document exceeds the maxBatchSizeBytes', () => { const documents = [ - { _id: '', _source: { type: 'dashboard', title: 'my saved object title ¹' } }, + { _id: 'foo', _source: { type: 'dashboard', title: 'my saved object title ¹' } }, { - _id: '', + _id: 'bar', _source: { type: 'dashboard', title: 'my saved object title ² with a very long title that exceeds max size bytes', }, }, - { _id: '', _source: { type: 'dashboard', title: 'my saved object title ®' } }, + { _id: 'baz', _source: { type: 'dashboard', title: 'my saved object title ®' } }, ]; - expect(createBatches(documents, INDEX, 178)).toEqual( + expect(createBatches({ documents, maxBatchSizeBytes: 120 })).toEqual( Either.left({ - maxBatchSizeBytes: 178, - docSizeBytes: 179, + maxBatchSizeBytes: 120, + docSizeBytes: 130, type: 'document_exceeds_batch_size_bytes', - document: documents[1], + documentId: documents[1]._id, }) ); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.ts index a591505f542c7..ec19f834d9ceb 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/create_batches.ts @@ -7,27 +7,50 @@ */ import * as Either from 'fp-ts/lib/Either'; -import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; -import { createBulkOperationBody } from '../actions/bulk_overwrite_transformed_documents'; +import type { SavedObjectsRawDoc, SavedObjectsRawDocSource } from '@kbn/core-saved-objects-server'; +import type { BulkOperationContainer } from '@elastic/elasticsearch/lib/api/types'; +import { createBulkDeleteOperationBody, createBulkIndexOperationTuple } from './helpers'; +import type { TransformErrorObjects } from '../core'; + +export type BulkIndexOperationTuple = [BulkOperationContainer, SavedObjectsRawDocSource]; +export type BulkOperation = BulkIndexOperationTuple | BulkOperationContainer; + +export interface CreateBatchesParams { + documents: SavedObjectsRawDoc[]; + corruptDocumentIds?: string[]; + transformErrors?: TransformErrorObjects[]; + maxBatchSizeBytes: number; +} + +export interface DocumentExceedsBatchSize { + documentId: string; + type: 'document_exceeds_batch_size_bytes'; + docSizeBytes: number; + maxBatchSizeBytes: number; +} /** * Creates batches of documents to be used by the bulk API. Each batch will * have a request body content length that's <= maxBatchSizeBytes */ -export function createBatches( - docs: SavedObjectsRawDoc[], - index: string, - maxBatchSizeBytes: number -) { +export function createBatches({ + documents, + corruptDocumentIds = [], + transformErrors = [], + maxBatchSizeBytes, +}: CreateBatchesParams): Either.Either { /* To build up the NDJSON request body we construct an array of objects like: * [ * {"index": ...} * {"title": "my saved object"} + * {"delete": ...} + * {"delete": ...} * ... * ] - * However, when we call JSON.stringify on this array the resulting string - * will be surrounded by `[]` which won't be present in the NDJSON so these - * two characters need to be removed from the size calculation. + * For indexing operations, createBulkIndexOperationTuple + * returns a tuple of the form [{operation, id}, {document}] + * Thus, for batch size calculations, we must take into account + * that this tuple's surrounding brackets `[]` won't be present in the NDJSON */ const BRACKETS_BYTES = 2; /* Each document in the NDJSON (including the last one) needs to be @@ -36,29 +59,68 @@ export function createBatches( */ const NDJSON_NEW_LINE_BYTES = 1; - const batches = [[]] as [SavedObjectsRawDoc[]]; + const BASE_DELETE_OPERATION_SIZE = Buffer.byteLength( + JSON.stringify(createBulkDeleteOperationBody('')), + 'utf8' + ); + + const batches: BulkOperation[][] = [[]]; let currBatch = 0; let currBatchSizeBytes = 0; - for (const doc of docs) { - const bulkOperationBody = createBulkOperationBody(doc, index); + + // group operations in batches of at most maxBatchSize + const assignToBatch = ( + operation: BulkOperationContainer | BulkIndexOperationTuple, + operationSizeBytes: number + ): boolean => { + operationSizeBytes += NDJSON_NEW_LINE_BYTES; + + if (operationSizeBytes > maxBatchSizeBytes) { + // the current operation (+ payload) does not even fit a single batch, fail! + return false; + } else if (currBatchSizeBytes + operationSizeBytes <= maxBatchSizeBytes) { + batches[currBatch].push(operation); + currBatchSizeBytes = currBatchSizeBytes + operationSizeBytes; + } else { + currBatch++; + batches[currBatch] = [operation]; + currBatchSizeBytes = operationSizeBytes; + } + return true; + }; + + // create index (update) operations for all transformed documents + for (const document of documents) { + const bulkIndexOperationBody = createBulkIndexOperationTuple(document); + // take into account that this tuple's surrounding brackets `[]` won't be present in the NDJSON const docSizeBytes = - Buffer.byteLength(JSON.stringify(bulkOperationBody), 'utf8') - - BRACKETS_BYTES + - NDJSON_NEW_LINE_BYTES; - if (docSizeBytes > maxBatchSizeBytes) { + Buffer.byteLength(JSON.stringify(bulkIndexOperationBody), 'utf8') - BRACKETS_BYTES; + if (!assignToBatch(bulkIndexOperationBody, docSizeBytes)) { return Either.left({ - type: 'document_exceeds_batch_size_bytes', + documentId: document._id, + type: 'document_exceeds_batch_size_bytes' as const, + docSizeBytes, + maxBatchSizeBytes, + }); + } + } + + // create delete operations for all corrupt documents + transform errors + const unwantedDocumentIds = [ + ...corruptDocumentIds, + ...transformErrors.map(({ rawId: documentId }) => documentId), + ]; + + for (const documentId of unwantedDocumentIds) { + const bulkDeleteOperationBody = createBulkDeleteOperationBody(documentId); + const docSizeBytes = BASE_DELETE_OPERATION_SIZE + Buffer.byteLength(documentId, 'utf8'); + if (!assignToBatch(bulkDeleteOperationBody, docSizeBytes)) { + return Either.left({ + documentId, + type: 'document_exceeds_batch_size_bytes' as const, docSizeBytes, maxBatchSizeBytes, - document: doc, }); - } else if (currBatchSizeBytes + docSizeBytes <= maxBatchSizeBytes) { - batches[currBatch].push(doc); - currBatchSizeBytes = currBatchSizeBytes + docSizeBytes; - } else { - currBatch++; - batches[currBatch] = [doc]; - currBatchSizeBytes = docSizeBytes; } } diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts index a7e71bc99e9e0..19ef5d66c0eb5 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts @@ -8,27 +8,29 @@ import { gt, valid } from 'semver'; import type { + BulkOperationContainer, QueryDslBoolQuery, QueryDslQueryContainer, } from '@elastic/elasticsearch/lib/api/types'; import * as Either from 'fp-ts/lib/Either'; +import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; import type { IndexMapping } from '@kbn/core-saved-objects-base-server-internal'; -import type { State } from '../state'; import type { AliasAction, FetchIndexResponse } from '../actions'; +import type { BulkIndexOperationTuple } from './create_batches'; /** * A helper function/type for ensuring that all control state's are handled. */ export function throwBadControlState(p: never): never; -export function throwBadControlState(controlState: any) { +export function throwBadControlState(controlState: unknown) { throw new Error('Unexpected control state: ' + controlState); } /** * A helper function/type for ensuring that all response types are handled. */ -export function throwBadResponse(state: State, p: never): never; -export function throwBadResponse(state: State, res: any): never { +export function throwBadResponse(state: { controlState: string }, p: never): never; +export function throwBadResponse(state: { controlState: string }, res: unknown): never { throw new Error( `${state.controlState} received unexpected action response: ` + JSON.stringify(res) ); @@ -132,11 +134,11 @@ export function addMustClausesToBoolQuery( /** * Add the given clauses to the 'must_not' of the given query * @param boolQuery the bool query to be enriched - * @param mustNotClauses the clauses to be added to a 'must_not' + * @param filterClauses the clauses to be added to a 'must_not' * @returns a new query container with the enriched query */ export function addMustNotClausesToBoolQuery( - mustNotClauses: QueryDslQueryContainer[], + filterClauses: QueryDslQueryContainer[], boolQuery?: QueryDslBoolQuery ): QueryDslQueryContainer { let mustNot: QueryDslQueryContainer[] = []; @@ -145,7 +147,7 @@ export function addMustNotClausesToBoolQuery( mustNot = mustNot.concat(boolQuery.must_not); } - mustNot.push(...mustNotClauses); + mustNot.push(...filterClauses); return { bool: { @@ -205,3 +207,28 @@ export function buildRemoveAliasActions( return [{ remove: { index, alias, must_exist: true } }]; }); } + +/** + * Given a document, creates a valid body to index the document using the Bulk API. + */ +export const createBulkIndexOperationTuple = (doc: SavedObjectsRawDoc): BulkIndexOperationTuple => { + return [ + { + index: { + _id: doc._id, + // use optimistic concurrency control to ensure that outdated + // documents are only overwritten once with the latest version + ...(typeof doc._seq_no !== 'undefined' && { if_seq_no: doc._seq_no }), + ...(typeof doc._primary_term !== 'undefined' && { if_primary_term: doc._primary_term }), + }, + }, + doc._source, + ]; +}; + +/** + * Given a document id, creates a valid body to delete the document using the Bulk API. + */ +export const createBulkDeleteOperationBody = (_id: string): BulkOperationContainer => ({ + delete: { _id }, +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts index 3c47ea01ecd72..c07538d1c1184 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts @@ -11,48 +11,51 @@ import * as Option from 'fp-ts/lib/Option'; import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; import type { IndexMapping } from '@kbn/core-saved-objects-base-server-internal'; import type { + BaseState, + CalculateExcludeFiltersState, + CheckTargetMappingsState, + CheckUnknownDocumentsState, + CheckVersionIndexReadyActions, + CleanupUnknownAndExcluded, + CleanupUnknownAndExcludedWaitForTaskState, + CloneTempToSource, + CreateNewTargetState, + CreateReindexTempState, FatalState, - State, - LegacySetWriteBlockState, - SetSourceWriteBlockState, LegacyCreateReindexTargetState, + LegacyDeleteState, LegacyReindexState, LegacyReindexWaitForTaskState, - LegacyDeleteState, - ReindexSourceToTempOpenPit, - ReindexSourceToTempRead, - ReindexSourceToTempClosePit, - ReindexSourceToTempTransform, - RefreshTarget, - UpdateTargetMappingsState, - UpdateTargetMappingsWaitForTaskState, + LegacySetWriteBlockState, + MarkVersionIndexReady, + MarkVersionIndexReadyConflict, + OutdatedDocumentsSearchClosePit, OutdatedDocumentsSearchOpenPit, OutdatedDocumentsSearchRead, - OutdatedDocumentsSearchClosePit, OutdatedDocumentsTransform, - MarkVersionIndexReady, - BaseState, - CreateReindexTempState, - MarkVersionIndexReadyConflict, - CreateNewTargetState, - CloneTempToSource, + PostInitState, + PrepareCompatibleMigration, + RefreshTarget, + ReindexSourceToTempClosePit, + ReindexSourceToTempIndexBulk, + ReindexSourceToTempOpenPit, + ReindexSourceToTempRead, + ReindexSourceToTempTransform, + SetSourceWriteBlockState, SetTempWriteBlock, - WaitForYellowSourceState, + State, TransformedDocumentsBulkIndex, - ReindexSourceToTempIndexBulk, - CheckUnknownDocumentsState, - CalculateExcludeFiltersState, - PostInitState, - CheckVersionIndexReadyActions, UpdateTargetMappingsMeta, - CheckTargetMappingsState, - PrepareCompatibleMigration, + UpdateTargetMappingsState, + UpdateTargetMappingsWaitForTaskState, + WaitForYellowSourceState, } from '../state'; import { type TransformErrorObjects, TransformSavedObjectDocumentError } from '../core'; import type { AliasAction, RetryableEsClientError } from '../actions'; import type { ResponseType } from '../next'; import { createInitialProgress } from './progress'; import { model } from './model'; +import type { BulkIndexOperationTuple, BulkOperation } from './create_batches'; describe('migrations v2 model', () => { const indexMapping: IndexMapping = { @@ -112,6 +115,26 @@ describe('migrations v2 model', () => { waitForMigrationCompletion: false, }; + const aProcessedDoc = { + _id: 'a:b', + _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, + }; + + const processedDocs: SavedObjectsRawDoc[] = [aProcessedDoc]; + + const bulkOperationBatches: BulkOperation[][] = [ + [ + [ + { + index: { + _id: aProcessedDoc._id, + }, + }, + aProcessedDoc._source, + ], + ], + ]; + describe('exponential retry delays for retryable_es_client_error', () => { let state: State = { ...baseState, @@ -1235,16 +1258,7 @@ describe('migrations v2 model', () => { }); describe('and mappings match (diffMappings == false)', () => { - const unchangedMappingsState: State = { - ...waitForYellowSourceState, - controlState: 'WAIT_FOR_YELLOW_SOURCE', - kibanaVersion: '7.12.0', // new version! - currentAlias: '.kibana', - versionAlias: '.kibana_7.12.0', - versionIndex: '.kibana_7.11.0_001', - }; - - test('WAIT_FOR_YELLOW_SOURCE -> PREPARE_COMPATIBLE_MIGRATION', () => { + test('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED', () => { const res: ResponseType<'WAIT_FOR_YELLOW_SOURCE'> = Either.right({ '.kibana_7.11.0_001': { aliases: { @@ -1255,44 +1269,11 @@ describe('migrations v2 model', () => { settings: {}, }, }); - const newState = model(unchangedMappingsState, res) as PrepareCompatibleMigration; + const newState = model(waitForYellowSourceState, res) as CleanupUnknownAndExcluded; - expect(newState.controlState).toEqual('PREPARE_COMPATIBLE_MIGRATION'); - expect(newState.targetIndexRawMappings).toEqual({ - _meta: { - migrationMappingPropertyHashes: { - new_saved_object_type: '4a11183eee21e6fbad864f7a30b39ad0', - }, - }, - properties: { - new_saved_object_type: { - properties: { - value: { - type: 'text', - }, - }, - }, - }, - }); - expect(newState.versionAlias).toEqual('.kibana_7.12.0'); - expect(newState.currentAlias).toEqual('.kibana'); - // will point to - expect(newState.targetIndex).toEqual('.kibana_7.11.0_001'); - expect(newState.preTransformDocsActions).toEqual([ - { - add: { - alias: '.kibana_7.12.0', - index: '.kibana_7.11.0_001', - }, - }, - { - remove: { - alias: '.kibana_7.11.0', - index: '.kibana_7.11.0_001', - must_exist: true, - }, - }, - ]); + expect(newState.controlState).toEqual('CLEANUP_UNKNOWN_AND_EXCLUDED'); + expect(newState.targetIndex).toEqual(baseState.versionIndex); + expect(newState.versionIndexReadyActions).toEqual(Option.none); }); }); @@ -1312,13 +1293,8 @@ describe('migrations v2 model', () => { }, }; - const changedMappingsState: State = { + const changedMappingsState: WaitForYellowSourceState = { ...waitForYellowSourceState, - controlState: 'WAIT_FOR_YELLOW_SOURCE', - kibanaVersion: '7.12.0', // new version! - currentAlias: '.kibana', - versionAlias: '.kibana_7.12.0', - versionIndex: '.kibana_7.11.0_001', sourceIndexMappings: actualMappings, }; @@ -1354,6 +1330,178 @@ describe('migrations v2 model', () => { }); }); + describe('CLEANUP_UNKNOWN_AND_EXCLUDED', () => { + const cleanupUnknownAndExcluded: CleanupUnknownAndExcluded = { + ...baseState, + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', + sourceIndex: Option.some('.kibana_7.11.0_001') as Option.Some, + sourceIndexMappings: baseState.targetIndexMappings, + targetIndex: baseState.versionIndex, + kibanaVersion: '7.12.0', // new version! + currentAlias: '.kibana', + versionAlias: '.kibana_7.12.0', + aliases: { + '.kibana': '.kibana_7.11.0_001', + '.kibana_7.11.0': '.kibana_7.11.0_001', + }, + versionIndexReadyActions: Option.none, + }; + + describe('if action succeeds', () => { + test('CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK', () => { + const res: ResponseType<'CLEANUP_UNKNOWN_AND_EXCLUDED'> = Either.right({ + type: 'cleanup_started' as const, + taskId: '1234', + unknownDocs: [], + errorsByType: {}, + }); + const newState = model(cleanupUnknownAndExcluded, res) as PrepareCompatibleMigration; + + expect(newState.controlState).toEqual('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK'); + // expect(newState.targetIndexRawMappings).toEqual(indexMapping); + // expect(newState.targetIndexMappings).toEqual(indexMapping); + // expect(newState.targetIndex).toEqual('.kibana_7.11.0_001'); + // expect(newState.preTransformDocsActions).toEqual([ + // { + // add: { + // alias: '.kibana_7.12.0', + // index: '.kibana_7.11.0_001', + // }, + // }, + // { + // remove: { + // alias: '.kibana_7.11.0', + // index: '.kibana_7.11.0_001', + // must_exist: true, + // }, + // }, + // ]); + }); + }); + + test('CLEANUP_UNKNOWN_AND_EXCLUDED -> FATAL if discardUnknownObjects=false', () => { + const res: ResponseType<'CLEANUP_UNKNOWN_AND_EXCLUDED'> = Either.left({ + type: 'unknown_docs_found' as const, + unknownDocs: [ + { id: 'dashboard:12', type: 'dashboard' }, + { id: 'foo:17', type: 'foo' }, + ], + }); + + const newState = model(cleanupUnknownAndExcluded, res); + + expect(newState).toMatchObject({ + controlState: 'FATAL', + reason: expect.stringContaining( + 'Migration failed because some documents were found which use unknown saved object types' + ), + }); + }); + }); + + describe('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK', () => { + const cleanupUnknownAndExcludedWaitForTask: CleanupUnknownAndExcludedWaitForTaskState = { + ...baseState, + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK', + deleteByQueryTaskId: '1234', + sourceIndex: Option.some('.kibana_7.11.0_001') as Option.Some, + sourceIndexMappings: baseState.targetIndexMappings, + targetIndex: baseState.versionIndex, + kibanaVersion: '7.12.0', // new version! + currentAlias: '.kibana', + versionAlias: '.kibana_7.12.0', + aliases: { + '.kibana': '.kibana_7.11.0_001', + '.kibana_7.11.0': '.kibana_7.11.0_001', + }, + versionIndexReadyActions: Option.none, + }; + + test('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK when response is left wait_for_task_completion_timeout', () => { + const res: ResponseType<'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK'> = Either.left({ + message: '[timeout_exception] Timeout waiting for ...', + type: 'wait_for_task_completion_timeout', + }); + const newState = model(cleanupUnknownAndExcludedWaitForTask, res); + expect(newState.controlState).toEqual('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK'); + expect(newState.retryCount).toEqual(1); + expect(newState.retryDelay).toEqual(2000); + }); + + test('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION if action succeeds', () => { + const res: ResponseType<'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK'> = Either.right({ + type: 'cleanup_successful' as const, + }); + const newState = model( + cleanupUnknownAndExcludedWaitForTask, + res + ) as PrepareCompatibleMigration; + + expect(newState.controlState).toEqual('PREPARE_COMPATIBLE_MIGRATION'); + expect(newState.targetIndexRawMappings).toEqual(indexMapping); + expect(newState.targetIndexMappings).toEqual(indexMapping); + expect(newState.targetIndex).toEqual('.kibana_7.11.0_001'); + expect(newState.preTransformDocsActions).toEqual([ + { + add: { + alias: '.kibana_7.12.0', + index: '.kibana_7.11.0_001', + }, + }, + { + remove: { + alias: '.kibana_7.11.0', + index: '.kibana_7.11.0_001', + must_exist: true, + }, + }, + ]); + }); + + test('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> CLEANUP_UNKNOWN_AND_EXCLUDED if the deleteQuery fails and we have some attempts left', () => { + const res: ResponseType<'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK'> = Either.left({ + type: 'cleanup_failed' as const, + failures: ['Failed to delete dashboard:12345', 'Failed to delete dashboard:67890'], + versionConflicts: 12, + }); + + const newState = model(cleanupUnknownAndExcludedWaitForTask, res); + + expect(newState).toMatchObject({ + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', + logs: [ + { + level: 'warning', + message: + 'Errors occurred whilst deleting unwanted documents. Another instance is probably updating or deleting documents in the same index. Retrying attempt 1.', + }, + ], + }); + }); + + test('CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> FAIL if the deleteQuery fails after N retries', () => { + const res: ResponseType<'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK'> = Either.left({ + type: 'cleanup_failed' as const, + failures: ['Failed to delete dashboard:12345', 'Failed to delete dashboard:67890'], + }); + + const newState = model( + { + ...cleanupUnknownAndExcludedWaitForTask, + retryCount: cleanupUnknownAndExcludedWaitForTask.retryAttempts, + }, + res + ); + + expect(newState).toMatchObject({ + controlState: 'FATAL', + reason: expect.stringContaining( + 'Migration failed because it was unable to delete unwanted documents from the .kibana_7.11.0_001 system index' + ), + }); + }); + }); + describe('CHECK_UNKNOWN_DOCUMENTS', () => { const mappingsWithUnknownType = { properties: { @@ -1536,7 +1684,7 @@ describe('migrations v2 model', () => { }); it('CALCULATE_EXCLUDE_FILTERS -> CREATE_REINDEX_TEMP if action succeeds with filters', () => { const res: ResponseType<'CALCULATE_EXCLUDE_FILTERS'> = Either.right({ - mustNotClauses: [{ term: { fieldA: 'abc' } }], + filterClauses: [{ term: { fieldA: 'abc' } }], errorsByType: { type1: new Error('an error!') }, }); const newState = model(state, res); @@ -1784,12 +1932,6 @@ describe('migrations v2 model', () => { transformErrors: [], progress: { processed: undefined, total: 1 }, }; - const processedDocs = [ - { - _id: 'a:b', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, - }, - ] as SavedObjectsRawDoc[]; it('REINDEX_SOURCE_TO_TEMP_TRANSFORM -> REINDEX_SOURCE_TO_TEMP_INDEX_BULK if action succeeded', () => { const res: ResponseType<'REINDEX_SOURCE_TO_TEMP_TRANSFORM'> = Either.right({ @@ -1798,7 +1940,7 @@ describe('migrations v2 model', () => { const newState = model(state, res) as ReindexSourceToTempIndexBulk; expect(newState.controlState).toEqual('REINDEX_SOURCE_TO_TEMP_INDEX_BULK'); expect(newState.currentBatch).toEqual(0); - expect(newState.transformedDocBatches).toEqual([processedDocs]); + expect(newState.bulkOperationBatches).toEqual(bulkOperationBatches); expect(newState.progress.processed).toBe(0); // Result of `(undefined ?? 0) + corruptDocumentsId.length` }); @@ -1854,18 +1996,10 @@ describe('migrations v2 model', () => { }); describe('REINDEX_SOURCE_TO_TEMP_INDEX_BULK', () => { - const transformedDocBatches = [ - [ - { - _id: 'a:b', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, - }, - ], - ] as [SavedObjectsRawDoc[]]; const reindexSourceToTempIndexBulkState: ReindexSourceToTempIndexBulk = { ...baseState, controlState: 'REINDEX_SOURCE_TO_TEMP_INDEX_BULK', - transformedDocBatches, + bulkOperationBatches, currentBatch: 0, versionIndexReadyActions: Option.none, sourceIndex: Option.some('.kibana') as Option.Some, @@ -2024,6 +2158,18 @@ describe('migrations v2 model', () => { preTransformDocsActions: [someAliasAction], }; + it('PREPARE_COMPATIBLE_MIGRATIONS -> REFRESH_TARGET if action succeeds and we must refresh the index', () => { + const res: ResponseType<'PREPARE_COMPATIBLE_MIGRATION'> = Either.right( + 'update_aliases_succeeded' + ); + const newState = model( + { ...state, mustRefresh: true }, + res + ) as OutdatedDocumentsSearchOpenPit; + expect(newState.controlState).toEqual('REFRESH_TARGET'); + expect(newState.versionIndexReadyActions).toEqual(Option.none); + }); + it('PREPARE_COMPATIBLE_MIGRATIONS -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT if action succeeds', () => { const res: ResponseType<'PREPARE_COMPATIBLE_MIGRATION'> = Either.right( 'update_aliases_succeeded' @@ -2033,6 +2179,19 @@ describe('migrations v2 model', () => { expect(newState.versionIndexReadyActions).toEqual(Option.none); }); + it('PREPARE_COMPATIBLE_MIGRATIONS -> REFRESH_TARGET if action fails because the alias is not found', () => { + const res: ResponseType<'PREPARE_COMPATIBLE_MIGRATION'> = Either.left({ + type: 'alias_not_found_exception', + }); + + const newState = model( + { ...state, mustRefresh: true }, + res + ) as OutdatedDocumentsSearchOpenPit; + expect(newState.controlState).toEqual('REFRESH_TARGET'); + expect(newState.versionIndexReadyActions).toEqual(Option.none); + }); + it('PREPARE_COMPATIBLE_MIGRATIONS -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT if action fails because the alias is not found', () => { const res: ResponseType<'PREPARE_COMPATIBLE_MIGRATION'> = Either.left({ type: 'alias_not_found_exception', @@ -2268,12 +2427,6 @@ describe('migrations v2 model', () => { progress: createInitialProgress(), }; describe('OUTDATED_DOCUMENTS_TRANSFORM if action succeeds', () => { - const processedDocs = [ - { - _id: 'a:b', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, - }, - ] as SavedObjectsRawDoc[]; test('OUTDATED_DOCUMENTS_TRANSFORM -> TRANSFORMED_DOCUMENTS_BULK_INDEX if action succeeds', () => { const res: ResponseType<'OUTDATED_DOCUMENTS_TRANSFORM'> = Either.right({ processedDocs }); const newState = model( @@ -2281,7 +2434,7 @@ describe('migrations v2 model', () => { res ) as TransformedDocumentsBulkIndex; expect(newState.controlState).toEqual('TRANSFORMED_DOCUMENTS_BULK_INDEX'); - expect(newState.transformedDocBatches).toEqual([processedDocs]); + expect(newState.bulkOperationBatches).toEqual(bulkOperationBatches); expect(newState.currentBatch).toEqual(0); expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); @@ -2367,30 +2520,28 @@ describe('migrations v2 model', () => { }); describe('TRANSFORMED_DOCUMENTS_BULK_INDEX', () => { - const transformedDocBatches = [ - [ - // batch 0 - { - _id: 'a:b', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, - }, - { - _id: 'a:c', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, - }, - ], - [ - // batch 1 - { - _id: 'a:d', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, + const idToIndexOperation = (_id: string): BulkIndexOperationTuple => [ + // "index" operations have a first part with the operation and the SO id + { + index: { + _id, }, - ], - ] as SavedObjectsRawDoc[][]; + }, + // and a second part with the object _source + { type: 'a', a: { name: `HOI ${_id}!` }, migrationVersion: {}, references: [] }, + // these two parts are then serialized to NDJSON by esClient and sent over with POST _bulk + ]; + + const customBulkOperationBatches: BulkOperation[][] = [ + // batch 0 + ['a:b', 'a:c'].map(idToIndexOperation), + // batch 1 + ['a:d'].map(idToIndexOperation), + ]; const transformedDocumentsBulkIndexState: TransformedDocumentsBulkIndex = { ...baseState, controlState: 'TRANSFORMED_DOCUMENTS_BULK_INDEX', - transformedDocBatches, + bulkOperationBatches: customBulkOperationBatches, currentBatch: 0, versionIndexReadyActions: Option.none, sourceIndex: Option.some('.kibana') as Option.Some, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts index 167a5d3771b78..4c2a9147eb125 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts @@ -9,7 +9,8 @@ import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; -import { type AliasAction, isTypeof } from '../actions'; +import { isTypeof } from '../actions'; +import type { AliasAction } from '../actions'; import type { AllActionStates, State } from '../state'; import type { ResponseType } from '../next'; import { @@ -278,30 +279,6 @@ export const model = (currentState: State, resW: ResponseType): ], }; } - } else if (stateP.controlState === 'PREPARE_COMPATIBLE_MIGRATION') { - const res = resW as ExcludeRetryableEsError>; - if (Either.isRight(res)) { - return { - ...stateP, - controlState: 'OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT', - }; - } else if (Either.isLeft(res)) { - // Note: if multiple newer Kibana versions are competing with each other to perform a migration, - // it might happen that another Kibana instance has deleted this instance's version index. - // NIT to handle this in properly, we'd have to add a PREPARE_COMPATIBLE_MIGRATION_CONFLICT step, - // similar to MARK_VERSION_INDEX_READY_CONFLICT. - if (isTypeof(res.left, 'alias_not_found_exception')) { - // We assume that the alias was already deleted by another Kibana instance - return { - ...stateP, - controlState: 'OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT', - }; - } else { - throwBadResponse(stateP, res.left as never); - } - } else { - throwBadResponse(stateP, res); - } } else if (stateP.controlState === 'LEGACY_SET_WRITE_BLOCK') { const res = resW as ExcludeRetryableEsError>; // If the write block is successfully in place @@ -457,35 +434,16 @@ export const model = (currentState: State, resW: ResponseType): stateP.sourceIndexMappings, /* expected */ stateP.targetIndexMappings - ) + ) && + Math.random() < 10 ) { - // The source index .kibana is pointing to. E.g: ".xx8.7.0_001" - const source = stateP.sourceIndex.value; - return { ...stateP, - controlState: 'PREPARE_COMPATIBLE_MIGRATION', - sourceIndex: Option.none, - targetIndex: source!, - targetIndexRawMappings: stateP.sourceIndexMappings, - targetIndexMappings: mergeMigrationMappingPropertyHashes( - stateP.targetIndexMappings, - stateP.sourceIndexMappings - ), - preTransformDocsActions: [ - // Point the version alias to the source index. This let's other Kibana - // instances know that a migration for the current version is "done" - // even though we may be waiting for document transformations to finish. - { add: { index: source!, alias: stateP.versionAlias } }, - ...buildRemoveAliasActions(source!, Object.keys(stateP.aliases), [ - stateP.currentAlias, - stateP.versionAlias, - ]), - ], + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', + targetIndex: stateP.sourceIndex.value!, // We preserve the same index, source == target (E.g: ".xx8.7.0_001") versionIndexReadyActions: Option.none, }; } else { - // the mappings have changed, but changes might still be compatible return { ...stateP, controlState: 'CHECK_UNKNOWN_DOCUMENTS', @@ -507,6 +465,133 @@ export const model = (currentState: State, resW: ResponseType): } else { return throwBadResponse(stateP, res); } + } else if (stateP.controlState === 'CLEANUP_UNKNOWN_AND_EXCLUDED') { + const res = resW as ExcludeRetryableEsError>; + if (Either.isRight(res)) { + if (res.right.unknownDocs.length) { + logs = [ + ...stateP.logs, + { level: 'warning', message: extractDiscardedUnknownDocs(res.right.unknownDocs) }, + ]; + } + + logs = [ + ...logs, + ...Object.entries(res.right.errorsByType).map(([soType, error]) => ({ + level: 'warning' as const, + message: `Ignored excludeOnUpgrade hook on type [${soType}] that failed with error: "${error.toString()}"`, + })), + ]; + + return { + ...stateP, + logs, + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK', + deleteByQueryTaskId: res.right.taskId, + }; + } else { + return { + ...stateP, + controlState: 'FATAL', + reason: extractUnknownDocFailureReason( + stateP.migrationDocLinks.resolveMigrationFailures, + res.left.unknownDocs + ), + }; + } + } else if (stateP.controlState === 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK') { + const res = resW as ExcludeRetryableEsError>; + if (Either.isRight(res)) { + const source = stateP.sourceIndex.value; + return { + ...stateP, + logs, + controlState: 'PREPARE_COMPATIBLE_MIGRATION', + mustRefresh: + stateP.mustRefresh || typeof res.right.deleted === 'undefined' || res.right.deleted > 0, + targetIndexRawMappings: stateP.sourceIndexMappings, + targetIndexMappings: mergeMigrationMappingPropertyHashes( + stateP.targetIndexMappings, + stateP.sourceIndexMappings + ), + preTransformDocsActions: [ + // Point the version alias to the source index. This let's other Kibana + // instances know that a migration for the current version is "done" + // even though we may be waiting for document transformations to finish. + { add: { index: source!, alias: stateP.versionAlias } }, + ...buildRemoveAliasActions(source!, Object.keys(stateP.aliases), [ + stateP.currentAlias, + stateP.versionAlias, + ]), + ], + }; + } else { + if (isTypeof(res.left, 'wait_for_task_completion_timeout')) { + // After waiting for the specified timeout, the task has not yet + // completed. Retry this step to see if the task has completed after an + // exponential delay. We will basically keep polling forever until the + // Elasticsearch task succeeds or fails. + return delayRetryState(stateP, res.left.message, Number.MAX_SAFE_INTEGER); + } else { + if (stateP.retryCount < stateP.retryAttempts) { + const retryCount = stateP.retryCount + 1; + const retryDelay = 1500 + 1000 * Math.random(); + return { + ...stateP, + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', + mustRefresh: true, + retryCount, + retryDelay, + logs: [ + ...stateP.logs, + { + level: 'warning', + message: `Errors occurred whilst deleting unwanted documents. Another instance is probably updating or deleting documents in the same index. Retrying attempt ${retryCount}.`, + }, + ], + }; + } else { + const failures = res.left.failures.length; + const versionConflicts = res.left.versionConflicts ?? 0; + + let reason = `Migration failed because it was unable to delete unwanted documents from the ${stateP.sourceIndex.value} system index (${failures} failures and ${versionConflicts} conflicts)`; + if (failures) { + reason += `:\n` + res.left.failures.map((failure: string) => `- ${failure}\n`).join(''); + } + return { + ...stateP, + controlState: 'FATAL', + reason, + }; + } + } + } + } else if (stateP.controlState === 'PREPARE_COMPATIBLE_MIGRATION') { + const res = resW as ExcludeRetryableEsError>; + if (Either.isRight(res)) { + return { + ...stateP, + controlState: stateP.mustRefresh ? 'REFRESH_TARGET' : 'OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT', + }; + } else if (Either.isLeft(res)) { + // Note: if multiple newer Kibana versions are competing with each other to perform a migration, + // it might happen that another Kibana instance has deleted this instance's version index. + // NIT to handle this in properly, we'd have to add a PREPARE_COMPATIBLE_MIGRATION_CONFLICT step, + // similar to MARK_VERSION_INDEX_READY_CONFLICT. + if (isTypeof(res.left, 'alias_not_found_exception')) { + // We assume that the alias was already deleted by another Kibana instance + return { + ...stateP, + controlState: stateP.mustRefresh + ? 'REFRESH_TARGET' + : 'OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT', + }; + } else { + throwBadResponse(stateP, res.left as never); + } + } else { + throwBadResponse(stateP, res); + } } else if (stateP.controlState === 'CHECK_UNKNOWN_DOCUMENTS') { const res = resW as ExcludeRetryableEsError>; @@ -579,7 +664,7 @@ export const model = (currentState: State, resW: ResponseType): if (Either.isRight(res)) { excludeOnUpgradeQuery = addMustNotClausesToBoolQuery( - res.right.mustNotClauses, + res.right.filterClauses, stateP.excludeOnUpgradeQuery?.bool ); @@ -733,10 +818,8 @@ export const model = (currentState: State, resW: ResponseType): (stateP.corruptDocumentIds.length === 0 && stateP.transformErrors.length === 0) || stateP.discardCorruptObjects ) { - const processedDocs = Either.isRight(res) - ? res.right.processedDocs - : res.left.processedDocs; - const batches = createBatches(processedDocs, stateP.tempIndex, stateP.maxBatchSizeBytes); + const documents = Either.isRight(res) ? res.right.processedDocs : res.left.processedDocs; + const batches = createBatches({ documents, maxBatchSizeBytes: stateP.maxBatchSizeBytes }); if (Either.isRight(batches)) { let corruptDocumentIds = stateP.corruptDocumentIds; let transformErrors = stateP.transformErrors; @@ -751,7 +834,7 @@ export const model = (currentState: State, resW: ResponseType): corruptDocumentIds, transformErrors, controlState: 'REINDEX_SOURCE_TO_TEMP_INDEX_BULK', // handles the actual bulk indexing into temp index - transformedDocBatches: batches.right, + bulkOperationBatches: batches.right, currentBatch: 0, progress, }; @@ -760,7 +843,7 @@ export const model = (currentState: State, resW: ResponseType): ...stateP, controlState: 'FATAL', reason: fatalReasonDocumentExceedsMaxBatchSizeBytes({ - _id: batches.left.document._id, + _id: batches.left.documentId, docSizeBytes: batches.left.docSizeBytes, maxBatchSizeBytes: batches.left.maxBatchSizeBytes, }), @@ -796,7 +879,7 @@ export const model = (currentState: State, resW: ResponseType): } else if (stateP.controlState === 'REINDEX_SOURCE_TO_TEMP_INDEX_BULK') { const res = resW as ExcludeRetryableEsError>; if (Either.isRight(res)) { - if (stateP.currentBatch + 1 < stateP.transformedDocBatches.length) { + if (stateP.currentBatch + 1 < stateP.bulkOperationBatches.length) { return { ...stateP, controlState: 'REINDEX_SOURCE_TO_TEMP_INDEX_BULK', @@ -938,25 +1021,40 @@ export const model = (currentState: State, resW: ResponseType): } else { // we don't have any more outdated documents and need to either fail or move on to updating the target mappings. if (stateP.corruptDocumentIds.length > 0 || stateP.transformErrors.length > 0) { - const transformFailureReason = extractTransformFailuresReason( - stateP.migrationDocLinks.resolveMigrationFailures, - stateP.corruptDocumentIds, - stateP.transformErrors - ); - return { - ...stateP, - controlState: 'FATAL', - reason: transformFailureReason, - }; - } else { - // If there are no more results we have transformed all outdated - // documents and we didn't encounter any corrupt documents or transformation errors - // and can proceed to the next step - return { - ...stateP, - controlState: 'OUTDATED_DOCUMENTS_SEARCH_CLOSE_PIT', - }; + if (!stateP.discardCorruptObjects) { + const transformFailureReason = extractTransformFailuresReason( + stateP.migrationDocLinks.resolveMigrationFailures, + stateP.corruptDocumentIds, + stateP.transformErrors + ); + return { + ...stateP, + controlState: 'FATAL', + reason: transformFailureReason, + }; + } + + // at this point, users have configured kibana to discard corrupt objects + // thus, we can ignore corrupt documents and transform errors and proceed with the migration + logs = [ + ...stateP.logs, + { + level: 'warning', + message: extractDiscardedCorruptDocs( + stateP.corruptDocumentIds, + stateP.transformErrors + ), + }, + ]; } + + // If there are no more results we have transformed all outdated + // documents and we didn't encounter any corrupt documents or transformation errors + // and can proceed to the next step + return { + ...stateP, + controlState: 'OUTDATED_DOCUMENTS_SEARCH_CLOSE_PIT', + }; } } else { throwBadResponse(stateP, res); @@ -968,20 +1066,36 @@ export const model = (currentState: State, resW: ResponseType): // Otherwise the progress might look off when there are errors. const progress = incrementProcessedProgress(stateP.progress, stateP.outdatedDocuments.length); - if (Either.isRight(res)) { - // we haven't seen corrupt documents or any transformation errors thus far in the migration - // index the migrated docs - if (stateP.corruptDocumentIds.length === 0 && stateP.transformErrors.length === 0) { - const batches = createBatches( - res.right.processedDocs, - stateP.targetIndex, - stateP.maxBatchSizeBytes - ); + if ( + Either.isRight(res) || + (isTypeof(res.left, 'documents_transform_failed') && stateP.discardCorruptObjects) + ) { + // we might have some transformation errors, but user has chosen to discard them + if ( + (stateP.corruptDocumentIds.length === 0 && stateP.transformErrors.length === 0) || + stateP.discardCorruptObjects + ) { + const documents = Either.isRight(res) ? res.right.processedDocs : res.left.processedDocs; + + let corruptDocumentIds = stateP.corruptDocumentIds; + let transformErrors = stateP.transformErrors; + + if (Either.isLeft(res)) { + corruptDocumentIds = [...stateP.corruptDocumentIds, ...res.left.corruptDocumentIds]; + transformErrors = [...stateP.transformErrors, ...res.left.transformErrors]; + } + + const batches = createBatches({ + documents, + corruptDocumentIds, + transformErrors, + maxBatchSizeBytes: stateP.maxBatchSizeBytes, + }); if (Either.isRight(batches)) { return { ...stateP, controlState: 'TRANSFORMED_DOCUMENTS_BULK_INDEX', - transformedDocBatches: batches.right, + bulkOperationBatches: batches.right, currentBatch: 0, hasTransformedDocs: true, progress, @@ -991,7 +1105,7 @@ export const model = (currentState: State, resW: ResponseType): ...stateP, controlState: 'FATAL', reason: fatalReasonDocumentExceedsMaxBatchSizeBytes({ - _id: batches.left.document._id, + _id: batches.left.documentId, docSizeBytes: batches.left.docSizeBytes, maxBatchSizeBytes: batches.left.maxBatchSizeBytes, }), @@ -1024,7 +1138,7 @@ export const model = (currentState: State, resW: ResponseType): } else if (stateP.controlState === 'TRANSFORMED_DOCUMENTS_BULK_INDEX') { const res = resW as ExcludeRetryableEsError>; if (Either.isRight(res)) { - if (stateP.currentBatch + 1 < stateP.transformedDocBatches.length) { + if (stateP.currentBatch + 1 < stateP.bulkOperationBatches.length) { return { ...stateP, controlState: 'TRANSFORMED_DOCUMENTS_BULK_INDEX', diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/retry_state.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/retry_state.ts index 532cc70347916..f6fb8bf8a1904 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/retry_state.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/retry_state.ts @@ -6,9 +6,16 @@ * Side Public License, v 1. */ -import { State } from '../state'; +import type { MigrationLog } from '../types'; -export const delayRetryState = ( +export interface RetryableState { + controlState: string; + retryCount: number; + retryDelay: number; + logs: MigrationLog[]; +} + +export const delayRetryState = ( state: S, errorMessage: string, /** How many times to retry a step that fails */ @@ -39,7 +46,7 @@ export const delayRetryState = ( }; } }; -export const resetRetryState = (state: S): S => { +export const resetRetryState = (state: S): S => { return { ...state, retryCount: 0, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts index 386786baf60c8..605dd149855e7 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts @@ -43,9 +43,12 @@ import type { WaitForMigrationCompletionState, CheckTargetMappingsState, PrepareCompatibleMigration, + CleanupUnknownAndExcluded, + CleanupUnknownAndExcludedWaitForTaskState, } from './state'; import type { TransformRawDocs } from './types'; import * as Actions from './actions'; +import { REMOVED_TYPES } from './core'; type ActionMap = ReturnType; @@ -63,12 +66,30 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra return { INIT: (state: InitState) => Actions.initAction({ client, indices: [state.currentAlias, state.versionAlias] }), - PREPARE_COMPATIBLE_MIGRATION: (state: PrepareCompatibleMigration) => - Actions.updateAliases({ client, aliasActions: state.preTransformDocsActions }), WAIT_FOR_MIGRATION_COMPLETION: (state: WaitForMigrationCompletionState) => Actions.fetchIndices({ client, indices: [state.currentAlias, state.versionAlias] }), WAIT_FOR_YELLOW_SOURCE: (state: WaitForYellowSourceState) => Actions.waitForIndexStatus({ client, index: state.sourceIndex.value, status: 'yellow' }), + CLEANUP_UNKNOWN_AND_EXCLUDED: (state: CleanupUnknownAndExcluded) => + Actions.cleanupUnknownAndExcluded({ + client, + indexName: state.sourceIndex.value, + discardUnknownDocs: state.discardUnknownObjects, + excludeOnUpgradeQuery: state.excludeOnUpgradeQuery, + excludeFromUpgradeFilterHooks: state.excludeFromUpgradeFilterHooks, + knownTypes: state.knownTypes, + removedTypes: REMOVED_TYPES, + }), + CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK: ( + state: CleanupUnknownAndExcludedWaitForTaskState + ) => + Actions.waitForDeleteByQueryTask({ + client, + taskId: state.deleteByQueryTaskId, + timeout: '120s', + }), + PREPARE_COMPATIBLE_MIGRATION: (state: PrepareCompatibleMigration) => + Actions.updateAliases({ client, aliasActions: state.preTransformDocsActions }), CHECK_UNKNOWN_DOCUMENTS: (state: CheckUnknownDocumentsState) => Actions.checkForUnknownDocs({ client, @@ -117,7 +138,7 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra Actions.bulkOverwriteTransformedDocuments({ client, index: state.tempIndex, - transformedDocs: state.transformedDocBatches[state.currentBatch], + operations: state.bulkOperationBatches[state.currentBatch], /** * Since we don't run a search against the target index, we disable "refresh" to speed up * the migration process. @@ -178,14 +199,14 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra Actions.bulkOverwriteTransformedDocuments({ client, index: state.targetIndex, - transformedDocs: state.transformedDocBatches[state.currentBatch], + operations: state.bulkOperationBatches[state.currentBatch], /** * Since we don't run a search against the target index, we disable "refresh" to speed up * the migration process. * Although any further step must run "refresh" for the target index - * before we reach out to the MARK_VERSION_INDEX_READY step. * Right now, it's performed during OUTDATED_DOCUMENTS_REFRESH step. */ + refresh: false, }), MARK_VERSION_INDEX_READY: (state: MarkVersionIndexReady) => Actions.updateAliases({ client, aliasActions: state.versionIndexReadyActions.value }), diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts index f3a59fadf2dd4..a091a2972343f 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts @@ -18,6 +18,7 @@ import type { ControlState } from './state_action_machine'; import type { AliasAction } from './actions'; import type { TransformErrorObjects } from './core'; import type { MigrationLog, Progress } from './types'; +import type { BulkOperation } from './model/create_batches'; export interface BaseState extends ControlState { /** The first part of the index name such as `.kibana` or `.kibana_task_manager` */ @@ -180,14 +181,37 @@ export interface PostInitState extends BaseState { */ readonly targetIndexRawMappings?: IndexMapping; readonly versionIndexReadyActions: Option.Option; - readonly outdatedDocumentsQuery: QueryDslQueryContainer; } +export interface SourceExistsState { + readonly sourceIndex: Option.Some; +} +export type BaseWithSource = BaseState & SourceExistsState; +export type PostInitWithSource = PostInitState & SourceExistsState; + export interface DoneState extends PostInitState { /** Migration completed successfully */ readonly controlState: 'DONE'; } +export interface CleanupUnknownAndExcluded extends PostInitWithSource { + /** Clean the source index, removing SOs with unknown and excluded types */ + readonly controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED'; + readonly sourceIndexMappings: IndexMapping; + readonly aliases: Record; + /** The cleanup operation has deleted one or more documents, we gotta refresh the index */ + readonly mustRefresh?: boolean; +} + +export interface CleanupUnknownAndExcludedWaitForTaskState extends PostInitWithSource { + readonly controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK'; + readonly deleteByQueryTaskId: string; + readonly sourceIndexMappings: IndexMapping; + readonly aliases: Record; + /** The cleanup operation has deleted one or more documents, we gotta refresh the index */ + readonly mustRefresh?: boolean; +} + /** * Compatibe migrations do not require migrating to a new index because all * schema changes are compatible with current index mappings. @@ -196,11 +220,13 @@ export interface DoneState extends PostInitState { * need to make sure that no older Kibana versions are still writing to target * index. */ -export interface PrepareCompatibleMigration extends PostInitState { +export interface PrepareCompatibleMigration extends PostInitWithSource { /** We have found a schema-compatible migration, this means we can optimise our migration steps */ readonly controlState: 'PREPARE_COMPATIBLE_MIGRATION'; /** Alias-level actions that prepare for this migration */ readonly preTransformDocsActions: AliasAction[]; + /** Indicates whether we must refresh the index */ + readonly mustRefresh?: boolean; } export interface FatalState extends BaseState { @@ -210,30 +236,26 @@ export interface FatalState extends BaseState { readonly reason: string; } -export interface WaitForYellowSourceState extends BaseState { +export interface WaitForYellowSourceState extends BaseWithSource { /** Wait for the source index to be yellow before reading from it. */ readonly controlState: 'WAIT_FOR_YELLOW_SOURCE'; - readonly sourceIndex: Option.Some; readonly sourceIndexMappings: IndexMapping; readonly aliases: Record; } -export interface CheckUnknownDocumentsState extends BaseState { +export interface CheckUnknownDocumentsState extends BaseWithSource { /** Check if any unknown document is present in the source index */ readonly controlState: 'CHECK_UNKNOWN_DOCUMENTS'; - readonly sourceIndex: Option.Some; readonly sourceIndexMappings: IndexMapping; } -export interface SetSourceWriteBlockState extends PostInitState { +export interface SetSourceWriteBlockState extends PostInitWithSource { /** Set a write block on the source index to prevent any further writes */ readonly controlState: 'SET_SOURCE_WRITE_BLOCK'; - readonly sourceIndex: Option.Some; } -export interface CalculateExcludeFiltersState extends PostInitState { +export interface CalculateExcludeFiltersState extends PostInitWithSource { readonly controlState: 'CALCULATE_EXCLUDE_FILTERS'; - readonly sourceIndex: Option.Some; } export interface CreateNewTargetState extends PostInitState { @@ -243,19 +265,17 @@ export interface CreateNewTargetState extends PostInitState { readonly versionIndexReadyActions: Option.Some; } -export interface CreateReindexTempState extends PostInitState { +export interface CreateReindexTempState extends PostInitWithSource { /** * Create a target index with mappings from the source index and registered * plugins */ readonly controlState: 'CREATE_REINDEX_TEMP'; - readonly sourceIndex: Option.Some; } -export interface ReindexSourceToTempOpenPit extends PostInitState { +export interface ReindexSourceToTempOpenPit extends PostInitWithSource { /** Open PIT to the source index */ readonly controlState: 'REINDEX_SOURCE_TO_TEMP_OPEN_PIT'; - readonly sourceIndex: Option.Some; } interface ReindexSourceToTempBatch extends PostInitState { @@ -282,24 +302,19 @@ export interface ReindexSourceToTempTransform extends ReindexSourceToTempBatch { export interface ReindexSourceToTempIndexBulk extends ReindexSourceToTempBatch { readonly controlState: 'REINDEX_SOURCE_TO_TEMP_INDEX_BULK'; - readonly transformedDocBatches: [SavedObjectsRawDoc[]]; + readonly bulkOperationBatches: BulkOperation[][]; readonly currentBatch: number; } -export type SetTempWriteBlock = PostInitState & { - /** - * - */ +export interface SetTempWriteBlock extends PostInitWithSource { readonly controlState: 'SET_TEMP_WRITE_BLOCK'; - readonly sourceIndex: Option.Some; -}; +} -export interface CloneTempToSource extends PostInitState { +export interface CloneTempToSource extends PostInitWithSource { /** * Clone the temporary reindex index into */ readonly controlState: 'CLONE_TEMP_TO_TARGET'; - readonly sourceIndex: Option.Some; } export interface RefreshTarget extends PostInitState { @@ -380,7 +395,7 @@ export interface TransformedDocumentsBulkIndex extends PostInitState { * Write the up-to-date transformed documents to the target index */ readonly controlState: 'TRANSFORMED_DOCUMENTS_BULK_INDEX'; - readonly transformedDocBatches: SavedObjectsRawDoc[][]; + readonly bulkOperationBatches: BulkOperation[][]; readonly currentBatch: number; readonly lastHitSortValue: number[] | undefined; readonly hasTransformedDocs: boolean; @@ -423,8 +438,7 @@ export interface MarkVersionIndexReadyConflict extends PostInitState { * If we're migrating from a legacy index we need to perform some additional * steps to prepare this index so that it can be used as a migration 'source'. */ -export interface LegacyBaseState extends PostInitState { - readonly sourceIndex: Option.Some; +export interface LegacyBaseState extends PostInitWithSource { readonly legacyPreMigrationDoneActions: AliasAction[]; /** * The mappings read from the legacy index, used to create a new reindex @@ -474,6 +488,8 @@ export type State = Readonly< | FatalState | InitState | PrepareCompatibleMigration + | CleanupUnknownAndExcluded + | CleanupUnknownAndExcludedWaitForTaskState | WaitForMigrationCompletionState | DoneState | WaitForYellowSourceState diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/actions/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/actions/index.ts new file mode 100644 index 0000000000000..92334d396adc0 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/actions/index.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { + IncompatibleClusterRoutingAllocation, + RetryableEsClientError, + WaitForTaskCompletionTimeout, + IndexNotFound, +} from '../../actions'; + +export { + initAction as init, + type InitActionParams, + type IncompatibleClusterRoutingAllocation, + type RetryableEsClientError, + type WaitForTaskCompletionTimeout, + type IndexNotFound, +} from '../../actions'; + +export interface ActionErrorTypeMap { + wait_for_task_completion_timeout: WaitForTaskCompletionTimeout; + incompatible_cluster_routing_allocation: IncompatibleClusterRoutingAllocation; + retryable_es_client_error: RetryableEsClientError; + index_not_found_exception: IndexNotFound; +} + +/** Type guard for narrowing the type of a left */ +export function isTypeof( + res: any, + typeString: T +): res is ActionErrorTypeMap[T] { + return res.type === typeString; +} diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/create_context.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/create_context.ts new file mode 100644 index 0000000000000..cc4c7b63d3993 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/create_context.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { MigratorContext } from './types'; +import type { MigrateIndexOptions } from '../migrate_index'; + +export type CreateContextOps = Omit; + +/** + * Create the context object that will be used for this index migration. + */ +export const createContext = ({ + types, + docLinks, + migrationConfig, + elasticsearchClient, + indexPrefix, + typeRegistry, + serializer, +}: CreateContextOps): MigratorContext => { + return { + indexPrefix, + types, + elasticsearchClient, + typeRegistry, + serializer, + maxRetryAttempts: migrationConfig.retryAttempts, + migrationDocLinks: docLinks.links.kibanaUpgradeSavedObjects, + }; +}; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.scss b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/index.ts similarity index 59% rename from src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.scss rename to packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/index.ts index c3d89f430d70c..9e7adc4c93868 100644 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.scss +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/index.ts @@ -6,15 +6,5 @@ * Side Public License, v 1. */ -// Temporary fix for lensApp icon not support ghost color -.solutionToolbar__primaryButton--dark { - .euiIcon path { - fill: $euiColorInk; - } -} - -.solutionToolbar__primaryButton--light { - .euiIcon path { - fill: $euiColorGhost; - } -} +export type { MigratorContext } from './types'; +export { createContext, type CreateContextOps } from './create_context'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/types.ts new file mode 100644 index 0000000000000..2603a5b69a681 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ISavedObjectTypeRegistry, + ISavedObjectsSerializer, +} from '@kbn/core-saved-objects-server'; +import type { DocLinks } from '@kbn/doc-links'; + +/** + * The set of static, precomputed values and services used by the ZDT migration + */ +export interface MigratorContext { + /** The first part of the index name such as `.kibana` or `.kibana_task_manager` */ + readonly indexPrefix: string; + /** Name of the types that are living in the index */ + readonly types: string[]; + /** The client to use for communications with ES */ + readonly elasticsearchClient: ElasticsearchClient; + /** The maximum number of retries to attempt for a failing action */ + readonly maxRetryAttempts: number; + /** DocLinks for savedObjects. to reference online documentation */ + readonly migrationDocLinks: DocLinks['kibanaUpgradeSavedObjects']; + /** SO serializer to use for migration */ + readonly serializer: ISavedObjectsSerializer; + /** The SO type registry to use for the migration */ + readonly typeRegistry: ISavedObjectTypeRegistry; +} diff --git a/src/plugins/files/common/register_default_file_kinds.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/index.ts similarity index 59% rename from src/plugins/files/common/register_default_file_kinds.ts rename to packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/index.ts index 37982c445cd16..99e5c2d9cec44 100644 --- a/src/plugins/files/common/register_default_file_kinds.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/index.ts @@ -6,10 +6,4 @@ * Side Public License, v 1. */ -import { getFileKindsRegistry } from './file_kinds_registry'; -import { defaultImageFileKind } from '.'; - -export function registerDefaultFileKinds() { - const registry = getFileKindsRegistry(); - registry.register(defaultImageFileKind); -} +export { runZeroDowntimeMigration, type RunZeroDowntimeMigrationOpts } from './run_zdt_migration'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.ts new file mode 100644 index 0000000000000..72ee369236e16 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { + type SavedObjectsMigrationConfigType, + type MigrationResult, +} from '@kbn/core-saved-objects-base-server-internal'; +import type { + ISavedObjectTypeRegistry, + ISavedObjectsSerializer, +} from '@kbn/core-saved-objects-server'; +import type { Logger } from '@kbn/logging'; +import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; +import { migrationStateActionMachine } from './migration_state_action_machine'; +import type { VersionedTransformer } from '../document_migrator'; +import { createContext } from './context'; +import { next } from './next'; +import { model } from './model'; +import { createInitialState } from './state'; + +export interface MigrateIndexOptions { + indexPrefix: string; + types: string[]; + /** The SO type registry to use for the migration */ + typeRegistry: ISavedObjectTypeRegistry; + /** Logger to use for migration output */ + logger: Logger; + /** The document migrator to use to convert the document */ + documentMigrator: VersionedTransformer; + /** The migration config to use for the migration */ + migrationConfig: SavedObjectsMigrationConfigType; + /** docLinks contract to use to link to documentation */ + docLinks: DocLinksServiceStart; + /** SO serializer to use for migration */ + serializer: ISavedObjectsSerializer; + /** The client to use for communications with ES */ + elasticsearchClient: ElasticsearchClient; +} + +export const migrateIndex = async ({ + logger, + ...options +}: MigrateIndexOptions): Promise => { + const context = createContext(options); + const initialState = createInitialState(context); + + return migrationStateActionMachine({ + initialState, + next: next(context), + model, + context, + logger, + }); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migration_state_action_machine.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migration_state_action_machine.ts new file mode 100644 index 0000000000000..8982a1a9c6c7e --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migration_state_action_machine.ts @@ -0,0 +1,150 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { errors as EsErrors } from '@elastic/elasticsearch'; +import type { Logger } from '@kbn/logging'; +import { + getErrorMessage, + getRequestDebugMeta, +} from '@kbn/core-elasticsearch-client-server-internal'; +import { logStateTransition, logActionResponse } from '../common/utils'; +import { type Next, stateActionMachine } from '../state_action_machine'; +import { cleanup } from '../migrations_state_machine_cleanup'; +import type { State } from './state'; +import type { MigratorContext } from './context'; + +/** + * A specialized migrations-specific state-action machine that: + * - logs messages in state.logs + * - logs state transitions + * - logs action responses + * - resolves if the final state is DONE + * - rejects if the final state is FATAL + * - catches and logs exceptions and then rejects with a migrations specific error + */ +export async function migrationStateActionMachine({ + initialState, + context, + next, + model, + logger, +}: { + initialState: State; + context: MigratorContext; + next: Next; + model: (state: State, res: any, context: MigratorContext) => State; + logger: Logger; +}) { + const startTime = Date.now(); + // Since saved object index names usually start with a `.` and can be + // configured by users to include several `.`'s we can't use a logger tag to + // indicate which messages come from which index upgrade. + const logMessagePrefix = `[${context.indexPrefix}] `; + let prevTimestamp = startTime; + let lastState: State | undefined; + try { + const finalState = await stateActionMachine( + initialState, + (state) => next(state), + (state, res) => { + lastState = state; + logActionResponse(logger, logMessagePrefix, state, res); + const newState = model(state, res, context); + // Redact the state to reduce the memory consumption and so that we + // don't log sensitive information inside documents by only keeping + // the _id's of documents + const redactedNewState = { + ...newState, + /* TODO: commented until we have model stages that process outdated docs. (attrs not on model atm) + ...{ + outdatedDocuments: ( + (newState as ReindexSourceToTempTransform).outdatedDocuments ?? [] + ).map( + (doc) => + ({ + _id: doc._id, + } as SavedObjectsRawDoc) + ), + }, + ...{ + transformedDocBatches: ( + (newState as ReindexSourceToTempIndexBulk).transformedDocBatches ?? [] + ).map((batches) => batches.map((doc) => ({ _id: doc._id }))) as [SavedObjectsRawDoc[]], + }, + */ + }; + + const now = Date.now(); + logStateTransition( + logger, + logMessagePrefix, + state, + redactedNewState as State, + now - prevTimestamp + ); + prevTimestamp = now; + return newState; + } + ); + + const elapsedMs = Date.now() - startTime; + if (finalState.controlState === 'DONE') { + logger.info(logMessagePrefix + `Migration completed after ${Math.round(elapsedMs)}ms`); + return { + status: 'patched' as const, + destIndex: context.indexPrefix, + elapsedMs, + }; + } else if (finalState.controlState === 'FATAL') { + try { + await cleanup(context.elasticsearchClient, finalState); + } catch (e) { + logger.warn('Failed to cleanup after migrations:', e.message); + } + return Promise.reject( + new Error( + `Unable to complete saved object migrations for the [${context.indexPrefix}] index: ` + + finalState.reason + ) + ); + } else { + throw new Error('Invalid terminating control state'); + } + } catch (e) { + try { + await cleanup(context.elasticsearchClient, lastState); + } catch (err) { + logger.warn('Failed to cleanup after migrations:', err.message); + } + if (e instanceof EsErrors.ResponseError) { + // Log the failed request. This is very similar to the + // elasticsearch-service's debug logs, but we log everything in single + // line until we have sub-ms resolution in our cloud logs. Because this + // is error level logs, we're also more careful and don't log the request + // body since this can very likely have sensitive saved objects. + const req = getRequestDebugMeta(e.meta); + const failedRequestMessage = `Unexpected Elasticsearch ResponseError: statusCode: ${ + req.statusCode + }, method: ${req.method}, url: ${req.url} error: ${getErrorMessage(e)},`; + logger.error(logMessagePrefix + failedRequestMessage); + throw new Error( + `Unable to complete saved object migrations for the [${context.indexPrefix}] index. Please check the health of your Elasticsearch cluster and try again. ${failedRequestMessage}` + ); + } else { + logger.error(e); + + const newError = new Error( + `Unable to complete saved object migrations for the [${context.indexPrefix}] index. ${e}` + ); + + // restore error stack to point to a source of the problem. + newError.stack = `[${e.stack}]`; + throw newError; + } + } +} diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/index.ts new file mode 100644 index 0000000000000..22733dcbc531b --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { model } from './model'; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_popover.tsx b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.test.mocks.ts similarity index 51% rename from src/plugins/presentation_util/public/components/solution_toolbar/items/primary_popover.tsx rename to packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.test.mocks.ts index 164d4c9b4a1a6..70faab1fdc8d5 100644 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_popover.tsx +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.test.mocks.ts @@ -6,12 +6,13 @@ * Side Public License, v 1. */ -import React from 'react'; +const realStages = jest.requireActual('./stages'); -import { SolutionToolbarPopover, Props as SolutionToolbarPopoverProps } from './popover'; +export const StageMocks = Object.keys(realStages).reduce((mocks, key) => { + mocks[key] = jest.fn().mockImplementation((state: unknown) => state); + return mocks; +}, {} as Record); -export type Props = Omit; - -export const PrimaryActionPopover = (props: Omit) => ( - -); +jest.doMock('./stages', () => { + return StageMocks; +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.test.ts new file mode 100644 index 0000000000000..b6c91e702bd2b --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.test.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { StageMocks } from './model.test.mocks'; +import * as Either from 'fp-ts/lib/Either'; +import { createContextMock, MockedMigratorContext } from '../test_helpers'; +import type { RetryableEsClientError } from '../../actions'; +import type { State, BaseState, FatalState } from '../state'; +import type { StateActionResponse } from './types'; +import { model } from './model'; + +describe('model', () => { + let context: MockedMigratorContext; + + beforeEach(() => { + context = createContextMock(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const baseState: BaseState = { + controlState: '42', + retryCount: 0, + retryDelay: 0, + logs: [], + }; + + const retryableError: RetryableEsClientError = { + type: 'retryable_es_client_error', + message: 'snapshot_in_progress_exception', + }; + + describe('retry behavior', () => { + test('increments retryCount, exponential retryDelay if an action fails with a retryable_es_client_error', () => { + let state: State = { + ...baseState, + controlState: 'INIT', + }; + + const states = new Array(5).fill(1).map(() => { + state = model(state, Either.left(retryableError), context); + return state; + }); + const retryState = states.map(({ retryCount, retryDelay }) => ({ retryCount, retryDelay })); + expect(retryState).toMatchInlineSnapshot(` + Array [ + Object { + "retryCount": 1, + "retryDelay": 2000, + }, + Object { + "retryCount": 2, + "retryDelay": 4000, + }, + Object { + "retryCount": 3, + "retryDelay": 8000, + }, + Object { + "retryCount": 4, + "retryDelay": 16000, + }, + Object { + "retryCount": 5, + "retryDelay": 32000, + }, + ] + `); + }); + + test('resets retryCount, retryDelay when an action succeeds', () => { + const state: State = { + ...baseState, + controlState: 'INIT', + retryCount: 5, + retryDelay: 32000, + }; + const res: StateActionResponse<'INIT'> = Either.right({ + '.kibana_7.11.0_001': { + aliases: {}, + mappings: { properties: {} }, + settings: {}, + }, + }); + const newState = model(state, res, context); + + expect(newState.retryCount).toEqual(0); + expect(newState.retryDelay).toEqual(0); + }); + + test('terminates to FATAL after retryAttempts retries', () => { + const state: State = { + ...baseState, + controlState: 'INIT', + retryCount: 15, + retryDelay: 64000, + }; + + const newState = model(state, Either.left(retryableError), context) as FatalState; + + expect(newState.controlState).toEqual('FATAL'); + expect(newState.reason).toMatchInlineSnapshot( + `"Unable to complete the INIT step after 15 attempts, terminating. The last failure message was: snapshot_in_progress_exception"` + ); + }); + }); + + describe('dispatching to correct stage', () => { + test('dispatching INIT state', () => { + const state: State = { + ...baseState, + controlState: 'INIT', + }; + const res: StateActionResponse<'INIT'> = Either.right({ + '.kibana_7.11.0_001': { + aliases: {}, + mappings: { properties: {} }, + settings: {}, + }, + }); + model(state, res, context); + + expect(StageMocks.init).toHaveBeenCalledTimes(1); + expect(StageMocks.init).toHaveBeenCalledWith(state, res, context); + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.ts new file mode 100644 index 0000000000000..2ea48bd1a58af --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/model.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import type { State, AllActionStates } from '../state'; +import type { ResponseType } from '../next'; +import { delayRetryState, resetRetryState } from '../../model/retry_state'; +import { throwBadControlState } from '../../model/helpers'; +import { isTypeof } from '../actions'; +import { MigratorContext } from '../context'; +import * as Stages from './stages'; +import { StateActionResponse } from './types'; + +export const model = ( + current: State, + response: ResponseType, + context: MigratorContext +): State => { + if (Either.isLeft(response)) { + if (isTypeof(response.left, 'retryable_es_client_error')) { + return delayRetryState(current, response.left.message, context.maxRetryAttempts); + } + } else { + current = resetRetryState(current); + } + + switch (current.controlState) { + case 'INIT': + return Stages.init(current, response as StateActionResponse<'INIT'>, context); + case 'DONE': + case 'FATAL': + // The state-action machine will never call the model in the terminating states + return throwBadControlState(current as never); + default: + return throwBadControlState(current); + } +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/index.ts new file mode 100644 index 0000000000000..aa12c6bed1b22 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { init } from './init'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/init.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/init.test.ts new file mode 100644 index 0000000000000..8105449c7fce8 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/init.test.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import { createContextMock, MockedMigratorContext } from '../../test_helpers'; +import type { InitState } from '../../state'; +import type { StateActionResponse } from '../types'; +import { init } from './init'; + +describe('Action: init', () => { + let context: MockedMigratorContext; + + const createState = (parts: Partial = {}): InitState => ({ + controlState: 'INIT', + retryDelay: 0, + retryCount: 0, + logs: [], + ...parts, + }); + + beforeEach(() => { + context = createContextMock(); + }); + + test('INIT -> DONE because its not implemented yet', () => { + const state = createState(); + const res: StateActionResponse<'INIT'> = Either.right({ + '.kibana_8.7.0_001': { + aliases: { + '.kibana': {}, + '.kibana_8.7.0': {}, + }, + mappings: { properties: {} }, + settings: {}, + }, + }); + + const newState = init(state, res, context); + + expect(newState.controlState).toEqual('DONE'); + }); + + test('INIT -> INIT when cluster routing allocation is incompatible', () => { + const state = createState(); + const res: StateActionResponse<'INIT'> = Either.left({ + type: 'incompatible_cluster_routing_allocation', + }); + + const newState = init(state, res, context); + + expect(newState.controlState).toEqual('INIT'); + expect(newState.retryCount).toEqual(1); + expect(newState.retryDelay).toEqual(2000); + expect(newState.logs).toHaveLength(1); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/init.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/init.ts new file mode 100644 index 0000000000000..78dccf237afca --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/stages/init.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Either from 'fp-ts/lib/Either'; +import { delayRetryState } from '../../../model/retry_state'; +import { throwBadResponse } from '../../../model/helpers'; +import { isTypeof } from '../../actions'; +import type { State } from '../../state'; +import type { ModelStage } from '../types'; + +export const init: ModelStage<'INIT', 'DONE' | 'FATAL'> = (state, res, context): State => { + if (Either.isLeft(res)) { + const left = res.left; + if (isTypeof(left, 'incompatible_cluster_routing_allocation')) { + const retryErrorMessage = `[${left.type}] Incompatible Elasticsearch cluster settings detected. Remove the persistent and transient Elasticsearch cluster setting 'cluster.routing.allocation.enable' or set it to a value of 'all' to allow migrations to proceed. Refer to ${context.migrationDocLinks.routingAllocationDisabled} for more information on how to resolve the issue.`; + return delayRetryState(state, retryErrorMessage, context.maxRetryAttempts); + } else { + return throwBadResponse(state, left); + } + } + + // nothing implemented yet, just going to 'DONE' + return { + ...state, + controlState: 'DONE', + }; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/types.ts new file mode 100644 index 0000000000000..6c8227794bb83 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/model/types.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ExcludeRetryableEsError } from '../../model/types'; +import type { MigratorContext } from '../context'; +import type { + AllActionStates, + AllControlStates, + StateFromActionState, + StateFromControlState, +} from '../state'; +import type { ResponseType } from '../next'; + +/** + * Utility type used to define the input of stage functions + */ +export type StateActionResponse = ExcludeRetryableEsError< + ResponseType +>; + +/** + * Defines a stage delegation function for the model + */ +export type ModelStage = ( + state: StateFromActionState, + res: StateActionResponse, + context: MigratorContext +) => StateFromControlState; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.ts new file mode 100644 index 0000000000000..329ba194b5957 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { AllActionStates, InitState, State } from './state'; +import type { MigratorContext } from './context'; +import * as Actions from './actions'; + +export type ActionMap = ReturnType; + +/** + * The response type of the provided control state's action. + * + * E.g. given 'INIT', provides the response type of the action triggered by + * `next` in the 'INIT' control state. + */ +export type ResponseType = Awaited< + ReturnType> +>; + +export const nextActionMap = (context: MigratorContext) => { + return { + INIT: (state: InitState) => + Actions.init({ client: context.elasticsearchClient, indices: [context.indexPrefix] }), + }; +}; + +export const next = (context: MigratorContext) => { + const map = nextActionMap(context); + + return (state: State) => { + const delay = any>(fn: F): (() => ReturnType) => { + return () => { + return state.retryDelay > 0 + ? new Promise((resolve) => setTimeout(resolve, state.retryDelay)).then(fn) + : fn(); + }; + }; + + if (state.controlState === 'DONE' || state.controlState === 'FATAL') { + // Return null if we're in one of the terminating states + return null; + } else { + // Otherwise return the delayed action + // We use an explicit cast as otherwise TS infers `(state: never) => ...` + // here because state is inferred to be the intersection of all states + // instead of the union. + const nextAction = map[state.controlState] as ( + state: State + ) => ReturnType; + return delay(nextAction(state)); + } + }; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.ts new file mode 100644 index 0000000000000..8a2686e23764b --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Logger } from '@kbn/logging'; +import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ISavedObjectTypeRegistry, + ISavedObjectsSerializer, +} from '@kbn/core-saved-objects-server'; +import { + type SavedObjectsMigrationConfigType, + type MigrationResult, +} from '@kbn/core-saved-objects-base-server-internal'; +import type { VersionedTransformer } from '../document_migrator'; +import { buildMigratorConfigs } from './utils'; +import { migrateIndex } from './migrate_index'; + +export interface RunZeroDowntimeMigrationOpts { + /** The kibana system index prefix. e.g `.kibana` */ + kibanaIndexPrefix: string; + /** The SO type registry to use for the migration */ + typeRegistry: ISavedObjectTypeRegistry; + /** Logger to use for migration output */ + logger: Logger; + /** The document migrator to use to convert the document */ + documentMigrator: VersionedTransformer; + /** The migration config to use for the migration */ + migrationConfig: SavedObjectsMigrationConfigType; + /** docLinks contract to use to link to documentation */ + docLinks: DocLinksServiceStart; + /** SO serializer to use for migration */ + serializer: ISavedObjectsSerializer; + /** The client to use for communications with ES */ + elasticsearchClient: ElasticsearchClient; +} + +export const runZeroDowntimeMigration = async ( + options: RunZeroDowntimeMigrationOpts +): Promise => { + const migratorConfigs = buildMigratorConfigs({ + kibanaIndexPrefix: options.kibanaIndexPrefix, + typeRegistry: options.typeRegistry, + }); + + return await Promise.all( + migratorConfigs.map((migratorConfig) => { + return migrateIndex({ + ...options, + ...migratorConfig, + }); + }) + ); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/create_initial_state.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/create_initial_state.ts new file mode 100644 index 0000000000000..ceb68b42b4a72 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/create_initial_state.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { InitState, State } from './types'; +import type { MigratorContext } from '../context'; + +export const createInitialState = (context: MigratorContext): State => { + const initialState: InitState = { + controlState: 'INIT', + logs: [], + retryCount: 0, + retryDelay: 0, + }; + return initialState; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/index.ts new file mode 100644 index 0000000000000..bff3ea15da4c2 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { + BaseState, + InitState, + DoneState, + FatalState, + State, + AllActionStates, + AllControlStates, + StateFromActionState, + StateFromControlState, +} from './types'; +export { createInitialState } from './create_initial_state'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/types.ts new file mode 100644 index 0000000000000..90a888a8a947c --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/state/types.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { MigrationLog } from '../../types'; +import type { ControlState } from '../../state_action_machine'; + +export interface BaseState extends ControlState { + readonly retryCount: number; + readonly retryDelay: number; + readonly logs: MigrationLog[]; +} + +export interface InitState extends BaseState { + readonly controlState: 'INIT'; +} + +/** Migration completed successfully */ +export interface DoneState extends BaseState { + readonly controlState: 'DONE'; +} + +/** Migration terminated with a failure */ +export interface FatalState extends BaseState { + readonly controlState: 'FATAL'; + /** The reason the migration was terminated */ + readonly reason: string; +} + +export type State = InitState | DoneState | FatalState; + +export type AllControlStates = State['controlState']; + +export type AllActionStates = Exclude; + +/** + * Manually maintained reverse-lookup map used by `StateFromAction` + */ +export interface ControlStateMap { + INIT: InitState; + FATAL: FatalState; + DONE: DoneState; +} + +/** + * Utility type to reverse lookup an `AllControlStates` to it's corresponding State subtype. + */ +export type StateFromControlState = ControlStateMap[T]; + +/** + * Utility type to reverse lookup an `AllActionStates` to it's corresponding State subtype. + */ +export type StateFromActionState = StateFromControlState; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.ts new file mode 100644 index 0000000000000..ded69aa02e7de --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + ElasticsearchClientMock, + elasticsearchClientMock, +} from '@kbn/core-elasticsearch-client-server-mocks'; +import { SavedObjectTypeRegistry } from '@kbn/core-saved-objects-base-server-internal'; +import { serializerMock } from '@kbn/core-saved-objects-base-server-mocks'; +import { docLinksServiceMock } from '@kbn/core-doc-links-server-mocks'; +import type { MigratorContext } from '../context'; + +export type MockedMigratorContext = Omit & { + elasticsearchClient: ElasticsearchClientMock; +}; + +export const createContextMock = ( + parts: Partial = {} +): MockedMigratorContext => { + const typeRegistry = new SavedObjectTypeRegistry(); + + return { + indexPrefix: '.kibana', + types: ['foo', 'bar'], + elasticsearchClient: elasticsearchClientMock.createElasticsearchClient(), + maxRetryAttempts: 15, + migrationDocLinks: docLinksServiceMock.createSetupContract().links.kibanaUpgradeSavedObjects, + typeRegistry, + serializer: serializerMock.create(), + ...parts, + }; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/index.ts new file mode 100644 index 0000000000000..8b0c329317c03 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { createContextMock, type MockedMigratorContext } from './context'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/utils/get_migrator_configs.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/utils/get_migrator_configs.ts new file mode 100644 index 0000000000000..79634c456c5d7 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/utils/get_migrator_configs.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ISavedObjectTypeRegistry } from '@kbn/core-saved-objects-server'; + +export interface MigratorConfig { + /** The index prefix for this migrator. e.g '.kibana' */ + indexPrefix: string; + /** The id of the types this migrator is in charge of */ + types: string[]; +} + +export const buildMigratorConfigs = ({ + typeRegistry, + kibanaIndexPrefix, +}: { + typeRegistry: ISavedObjectTypeRegistry; + kibanaIndexPrefix: string; +}): MigratorConfig[] => { + const configMap = new Map(); + typeRegistry.getAllTypes().forEach((type) => { + const typeIndexPrefix = type.indexPattern ?? kibanaIndexPrefix; + if (!configMap.has(typeIndexPrefix)) { + configMap.set(typeIndexPrefix, { + indexPrefix: typeIndexPrefix, + types: [], + }); + } + const migratorConfig = configMap.get(typeIndexPrefix)!; + migratorConfig.types.push(type.name); + }); + return [...configMap.values()]; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/utils/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/utils/index.ts new file mode 100644 index 0000000000000..f96ea531e460d --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/utils/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { buildMigratorConfigs, type MigratorConfig } from './get_migrator_configs'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json b/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json index d1751da1050f5..e56ee4e2c3234 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json @@ -30,6 +30,7 @@ "@kbn/doc-links", "@kbn/safer-lodash-set", "@kbn/logging-mocks", + "@kbn/core-saved-objects-base-server-mocks", ], "exclude": [ "target/**/*", diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-mocks/src/kibana_migrator.mock.ts b/packages/core/saved-objects/core-saved-objects-migration-server-mocks/src/kibana_migrator.mock.ts index e7df2a0363a26..a0d7ac83fe74a 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-mocks/src/kibana_migrator.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-mocks/src/kibana_migrator.mock.ts @@ -12,7 +12,10 @@ import type { IKibanaMigrator, KibanaMigratorStatus, } from '@kbn/core-saved-objects-base-server-internal'; -import { buildActiveMappings, mergeTypes } from '@kbn/core-saved-objects-migration-server-internal'; +import { + buildActiveMappings, + buildTypesMappings, +} from '@kbn/core-saved-objects-migration-server-internal'; const defaultSavedObjectTypes: SavedObjectsType[] = [ { @@ -57,7 +60,7 @@ const createMigrator = ( ), }; - mockMigrator.getActiveMappings.mockReturnValue(buildActiveMappings(mergeTypes(types))); + mockMigrator.getActiveMappings.mockReturnValue(buildActiveMappings(buildTypesMappings(types))); mockMigrator.migrateDocument.mockImplementation((doc) => doc); return mockMigrator; }; diff --git a/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts b/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts index 8df9102719466..11ec2f0984199 100644 --- a/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts +++ b/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts @@ -176,5 +176,28 @@ describe('loadActions hooks', () => { expect(result.current.value).toEqual([[actionEnabled], [actionEnabled]]); }); + + it('should re-render when contexts is changed', async () => { + const { result, rerender, waitForNextUpdate } = renderHook(useBulkLoadActions, { + initialProps: [actionContext], + }); + + await waitForNextUpdate(); + expect(mockGetActions).toHaveBeenCalledWith(actionContext); + + rerender([actionContext2]); + await waitForNextUpdate(); + expect(mockGetActions).toHaveBeenCalledWith(actionContext2); + + mockGetActions.mockClear(); + + rerender([]); + await waitForNextUpdate(); + expect(mockGetActions).toHaveBeenCalledTimes(0); + + expect(result.current.value).toBeInstanceOf(Array); + expect(result.current.value).toHaveLength(0); + expect(result.current.loading).toBe(false); + }); }); }); diff --git a/packages/kbn-cell-actions/src/hooks/use_load_actions.ts b/packages/kbn-cell-actions/src/hooks/use_load_actions.ts index 54e6843bac279..6eece48655be3 100644 --- a/packages/kbn-cell-actions/src/hooks/use_load_actions.ts +++ b/packages/kbn-cell-actions/src/hooks/use_load_actions.ts @@ -66,7 +66,7 @@ export const useBulkLoadActions = ( ) ) ), - [] + [contexts] ); useThrowError(error); return actionsState; diff --git a/packages/kbn-cypress-config/index.ts b/packages/kbn-cypress-config/index.ts index eed0d71288115..58abd54a56f69 100644 --- a/packages/kbn-cypress-config/index.ts +++ b/packages/kbn-cypress-config/index.ts @@ -51,6 +51,8 @@ export function defineCypressConfig(options?: Cypress.ConfigOptions) { on(event, task); }, config); + + return config; } }, }, diff --git a/packages/shared-ux/button_toolbar/index.ts b/packages/shared-ux/button_toolbar/index.ts index 4e570029d7927..e290df34a01b3 100644 --- a/packages/shared-ux/button_toolbar/index.ts +++ b/packages/shared-ux/button_toolbar/index.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -export { PrimaryButton, IconButtonGroup, AddFromLibraryButton } from './src/buttons'; +export { ToolbarButton, IconButtonGroup, AddFromLibraryButton } from './src/buttons'; export type { AddFromLibraryButtonProps, IconButtonGroupProps, + ToolbarButtonProps, IconButton, - PrimaryButtonProps, } from './src/buttons'; export { ToolbarPopover } from './src/popover'; @@ -19,4 +19,4 @@ export type { ToolbarPopoverProps } from './src/popover'; export { Toolbar } from './src/toolbar'; export type { ToolbarProps } from './src/toolbar'; -export type { ToolbarButton } from './src/toolbar'; +export type { ToolbarButtonType } from './src/toolbar'; diff --git a/packages/shared-ux/button_toolbar/src/buttons/add_from_library/__snapshots__/add_from_library.test.tsx.snap b/packages/shared-ux/button_toolbar/src/buttons/add_from_library/__snapshots__/add_from_library.test.tsx.snap index 46ed9f7f6f769..a9e5ff8226fa9 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/add_from_library/__snapshots__/add_from_library.test.tsx.snap +++ b/packages/shared-ux/button_toolbar/src/buttons/add_from_library/__snapshots__/add_from_library.test.tsx.snap @@ -1,8 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` is rendered 1`] = ` +exports[` is rendered 1`] = ` -`; diff --git a/packages/shared-ux/button_toolbar/src/buttons/primary/primary.tsx b/packages/shared-ux/button_toolbar/src/buttons/primary/primary.tsx deleted file mode 100644 index 4d2975db2682b..0000000000000 --- a/packages/shared-ux/button_toolbar/src/buttons/primary/primary.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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { EuiButton } from '@elastic/eui'; -import { EuiButtonPropsForButton } from '@elastic/eui/src/components/button/button'; - -/** - * Props for `PrimaryButton`. - */ -export interface Props extends Pick { - label: string; -} - -/** - * A primary action button, usually appearing first in the toolbar. - */ -export const PrimaryButton = ({ label, iconSide = 'left', ...rest }: Props) => { - return ( - - {label} - - ); -}; diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap new file mode 100644 index 0000000000000..e39fd8be3a02b --- /dev/null +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` is rendered - default 1`] = ` + +`; + +exports[` is rendered - primary 1`] = ` + +`; diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/index.ts b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/index.ts new file mode 100644 index 0000000000000..335aa2bc4fe41 --- /dev/null +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { ToolbarButton } from './toolbar_button'; +export type { Props as ToolbarButtonProps } from './toolbar_button'; diff --git a/packages/shared-ux/button_toolbar/src/buttons/primary/primary.stories.tsx b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx similarity index 54% rename from packages/shared-ux/button_toolbar/src/buttons/primary/primary.stories.tsx rename to packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx index fb3b53b160f4c..580d894ecd042 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/primary/primary.stories.tsx +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx @@ -7,37 +7,42 @@ */ import React from 'react'; - -import { PrimaryButton as Component } from './primary'; +import { ToolbarButton as Component } from './toolbar_button'; import mdx from '../../../README.mdx'; -const argTypes = { - iconType: { - control: { - type: 'radio', - expanded: true, - options: ['apps', 'logoGithub', 'folderCheck', 'documents'], - }, - }, -}; - -type Params = Record; - export default { title: 'Button Toolbar/Buttons', - description: 'A primary button that is a part of a toolbar.', + description: 'A button that is a part of a toolbar.', parameters: { docs: { page: mdx, }, }, - argTypes, }; -export const PrimaryButton = ({ iconType }: Params) => { - return ; +const argTypes = { + buttonType: { + defaultValue: 'empty', + control: { + type: 'radio', + options: ['empty', 'primary'], + }, + }, + iconSide: { + defaultValue: 'left', + control: { + type: 'radio', + options: ['left', 'right', 'undefined'], + }, + }, }; -PrimaryButton.args = { - iconType: 'apps', +type Params = Record; + +export const ToolbarButton = ({ buttonType, iconSide }: Params) => { + return ( + + ); }; + +ToolbarButton.argTypes = argTypes; diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts new file mode 100644 index 0000000000000..162e81bb4efcb --- /dev/null +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { UseEuiTheme } from '@elastic/eui'; + +export const ToolbarButtonStyles = ({ euiTheme }: UseEuiTheme) => { + return { + emptyButton: { + backgroundColor: euiTheme.colors.emptyShade, + border: `${euiTheme.border.thin} !important`, + color: `${euiTheme.colors.text}`, + }, + }; +}; diff --git a/packages/shared-ux/button_toolbar/src/buttons/primary/primary.test.tsx b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx similarity index 54% rename from packages/shared-ux/button_toolbar/src/buttons/primary/primary.test.tsx rename to packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx index 8478ca1842c41..74b5fde37f5ff 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/primary/primary.test.tsx +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx @@ -9,17 +9,24 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { PrimaryButton } from './primary'; +import { ToolbarButton } from './toolbar_button'; describe('', () => { - test('is rendered', () => { - const component = mountWithIntl(); + test('is rendered - default', () => { + const component = mountWithIntl( 'click'} />); expect(component.render()).toMatchSnapshot(); }); - test('it can be passed a functional onClick handler', () => { + test('is rendered - primary', () => { + const component = mountWithIntl( + 'click'} /> + ); + expect(component.render()).toMatchSnapshot(); + }); + + test('accepts an onClick handler', () => { const mockHandler = jest.fn(); - const component = mountWithIntl(); + const component = mountWithIntl(); component.find('button').simulate('click'); expect(mockHandler).toHaveBeenCalled(); }); diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx new file mode 100644 index 0000000000000..3d04e689e4820 --- /dev/null +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiButton, useEuiTheme } from '@elastic/eui'; +import { EuiButtonPropsForButton } from '@elastic/eui/src/components/button/button'; + +import { ToolbarButtonStyles } from './toolbar_button.styles'; + +type ToolbarButtonTypes = 'primary' | 'empty'; + +/** + * Props for `PrimaryButton`. + */ +export interface Props + extends Pick { + label: string; + type?: ToolbarButtonTypes; +} + +export const ToolbarButton: React.FunctionComponent = ({ + label, + type = 'empty', + iconSide = 'left', + ...rest +}) => { + const euiTheme = useEuiTheme(); + const toolbarButtonStyleProps: EuiButtonPropsForButton = + type === 'primary' + ? { color: 'primary', fill: true } + : { color: 'text', css: ToolbarButtonStyles(euiTheme).emptyButton }; + + return ( + + {label} + + ); +}; diff --git a/packages/shared-ux/button_toolbar/src/popover/__snapshots__/popover.test.tsx.snap b/packages/shared-ux/button_toolbar/src/popover/__snapshots__/popover.test.tsx.snap index 6129d515e3a7f..9b4ac4a0ddac6 100644 --- a/packages/shared-ux/button_toolbar/src/popover/__snapshots__/popover.test.tsx.snap +++ b/packages/shared-ux/button_toolbar/src/popover/__snapshots__/popover.test.tsx.snap @@ -9,7 +9,7 @@ exports[` is rendered 1`] = ` class="euiPopover__anchor css-16vtueo-render" >
diff --git a/packages/shared-ux/button_toolbar/src/popover/popover.stories.tsx b/packages/shared-ux/button_toolbar/src/popover/popover.stories.tsx index e0c37b035cbd9..f59dbc242dd74 100644 --- a/packages/shared-ux/button_toolbar/src/popover/popover.stories.tsx +++ b/packages/shared-ux/button_toolbar/src/popover/popover.stories.tsx @@ -14,10 +14,17 @@ import { ToolbarPopover as Component } from './popover'; import mdx from '../../README.mdx'; const argTypes = { - iconSide: { + showIcon: { + defaultValue: true, + control: { + type: 'boolean', + }, + }, + buttonType: { + defaultValue: 'empty', control: { type: 'radio', - options: ['left', 'right', 'undefined'], + options: ['empty', 'primary'], }, }, }; @@ -35,12 +42,12 @@ export default { argTypes, }; -export const Popover = ({ iconSide }: Params) => { +export const Popover = ({ showIcon, buttonType }: Params) => { return ( {() => ( @@ -72,6 +79,4 @@ export const Popover = ({ iconSide }: Params) => { ); }; -Popover.args = { - iconSide: 'left', -}; +Popover.argTypes = argTypes; diff --git a/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx b/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx index afdf0007f8883..b03cb9e63d460 100644 --- a/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx +++ b/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx @@ -15,7 +15,6 @@ describe('', () => { test('is rendered', () => { const isOpen = true; const component = mountWithIntl( !isOpen} />); - expect(component.render()).toMatchSnapshot(); }); @@ -30,4 +29,45 @@ describe('', () => { component.simulate('click'); expect(mockHandler).toHaveBeenCalled(); }); + + test('defaults to a bordered empty button', () => { + const isOpen = true; + const component = mountWithIntl( !isOpen} />); + const button = component.find('EuiButton'); + expect(button.prop('color')).toBe('text'); + expect(button.prop('css')).toMatchObject({ + backgroundColor: '#FFF', + border: '1px solid #D3DAE6 !important', + color: '#343741', + }); + }); + + test('accepts a button type', () => { + const isOpen = true; + const component = mountWithIntl( + !isOpen} /> + ); + const button = component.find('EuiButton'); + expect(button.prop('color')).toBe('primary'); + }); + + test('if not given an iconType, render arrowDown on the right', () => { + const isOpen = false; + + const component = mountWithIntl( !isOpen} />); + const button = component.find('EuiButton'); + expect(button.prop('iconType')).toBe('arrowDown'); + expect(button.prop('iconSide')).toBe('right'); + }); + + test('if given an iconType, render it on the left', () => { + const isOpen = false; + + const component = mountWithIntl( + !isOpen} /> + ); + const button = component.find('EuiButton'); + expect(button.prop('iconType')).toBe('plusInCircle'); + expect(button.prop('iconSide')).toBe('left'); + }); }); diff --git a/packages/shared-ux/button_toolbar/src/popover/popover.tsx b/packages/shared-ux/button_toolbar/src/popover/popover.tsx index fdf60c1f0d5fa..7e7f6c24e2174 100644 --- a/packages/shared-ux/button_toolbar/src/popover/popover.tsx +++ b/packages/shared-ux/button_toolbar/src/popover/popover.tsx @@ -10,9 +10,9 @@ import React, { useState } from 'react'; import { EuiPopover } from '@elastic/eui'; import { Props as EuiPopoverProps } from '@elastic/eui/src/components/popover/popover'; -import { PrimaryButton, Props as ButtonProps } from '../buttons/primary/primary'; +import { ToolbarButtonProps, ToolbarButton } from '../buttons'; -type AllowedButtonProps = Omit; +type AllowedButtonProps = Omit; type AllowedPopoverProps = Omit< EuiPopoverProps, 'button' | 'isOpen' | 'closePopover' | 'anchorPosition' @@ -29,13 +29,18 @@ export type Props = AllowedButtonProps & /** * A button which opens a popover of additional actions within the toolbar. */ -export const ToolbarPopover = ({ label, iconType, children, iconSide, ...popover }: Props) => { +export const ToolbarPopover = ({ type, label, iconType, children, ...popover }: Props) => { const [isOpen, setIsOpen] = useState(false); const onButtonClick = () => setIsOpen((status) => !status); const closePopover = () => setIsOpen(false); - const button = ; + const button = ( + + ); return ( // the following ts-ignore is needed until typings/* directory is exposed for consumption to packages diff --git a/packages/shared-ux/button_toolbar/src/toolbar/index.ts b/packages/shared-ux/button_toolbar/src/toolbar/index.ts index b0e09e92f1528..99db9450dd4ba 100644 --- a/packages/shared-ux/button_toolbar/src/toolbar/index.ts +++ b/packages/shared-ux/button_toolbar/src/toolbar/index.ts @@ -10,4 +10,4 @@ export { Toolbar } from './toolbar'; export type { Props as ToolbarProps } from './toolbar'; -export type { ToolbarButton } from './toolbar'; +export type { ToolbarButtonType } from './toolbar'; diff --git a/packages/shared-ux/button_toolbar/src/toolbar/toolbar.stories.tsx b/packages/shared-ux/button_toolbar/src/toolbar/toolbar.stories.tsx index 61bcf4bb4153f..34fb09227b04c 100644 --- a/packages/shared-ux/button_toolbar/src/toolbar/toolbar.stories.tsx +++ b/packages/shared-ux/button_toolbar/src/toolbar/toolbar.stories.tsx @@ -12,7 +12,7 @@ import { action } from '@storybook/addon-actions'; import { EuiContextMenu } from '@elastic/eui'; import { Toolbar } from './toolbar'; -import { AddFromLibraryButton, IconButtonGroup, PrimaryButton } from '../buttons'; +import { AddFromLibraryButton, IconButtonGroup, ToolbarButton } from '../buttons'; import { ToolbarPopover } from '../popover'; const iconButtons = [ @@ -45,9 +45,21 @@ const iconButtons = [ ]; const primaryButtonConfigs = { - Generic: , + Generic: ( + + ), Canvas: ( - + {() => ( ), Dashboard: ( - + ), }; @@ -96,14 +116,17 @@ const extraButtonConfigs = { { name: 'Lens', icon: 'lensApp', + onClick: action('Lens'), }, { name: 'Maps', icon: 'logoMaps', + onClick: action('Maps'), }, { name: 'TSVB', icon: 'visVisualBuilder', + onClick: action('TSVB'), }, ], }, @@ -156,9 +179,13 @@ const Template: Story<{ showAddFromLibraryButton: boolean; }> = ({ iconButtonCount, solution, showAddFromLibraryButton }) => { const primaryButton = primaryButtonConfigs[solution]; - const extraButtons = extraButtonConfigs[solution]; + const extraButtons = showAddFromLibraryButton + ? [ + ...(extraButtonConfigs[solution] ?? []), + , + ] + : extraButtonConfigs[solution]; let iconButtonGroup; - let addFromLibraryButton; if (iconButtonCount > 0) { iconButtonGroup = ( @@ -166,17 +193,12 @@ const Template: Story<{ ); } - if (showAddFromLibraryButton) { - addFromLibraryButton = ; - } - return ( {{ primaryButton, iconButtonGroup, extraButtons, - addFromLibraryButton, }} ); diff --git a/packages/shared-ux/button_toolbar/src/toolbar/toolbar.test.tsx b/packages/shared-ux/button_toolbar/src/toolbar/toolbar.test.tsx index 729695edab5e8..9aa561af61781 100644 --- a/packages/shared-ux/button_toolbar/src/toolbar/toolbar.test.tsx +++ b/packages/shared-ux/button_toolbar/src/toolbar/toolbar.test.tsx @@ -10,11 +10,13 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { Toolbar } from './toolbar'; -import { PrimaryButton } from '../buttons'; +import { ToolbarButton } from '../buttons'; describe('', () => { test('is rendered', () => { - const primaryButton = 'click'} />; + const primaryButton = ( + 'click'} /> + ); const children = { primaryButton }; const component = mountWithIntl(); @@ -23,7 +25,9 @@ describe('', () => { test('onClick works as expected when the primary button is clicked', () => { const mockClickHandler = jest.fn(); - const primaryButton = ; + const primaryButton = ( + + ); const children = { primaryButton }; const component = mountWithIntl(); component.find('button').simulate('click'); diff --git a/packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx b/packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx index a195ca1b4c3be..eef0ce05eed6e 100644 --- a/packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx +++ b/packages/shared-ux/button_toolbar/src/toolbar/toolbar.tsx @@ -8,19 +8,19 @@ import React, { ReactElement } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - import { i18n } from '@kbn/i18n'; -import { IconButtonGroup, PrimaryButton } from '../buttons'; + import { ToolbarPopover } from '../popover'; +import { IconButtonGroup, ToolbarButton } from '../buttons'; /** type for cases with both button or a popover could be used */ -export type ToolbarButton = typeof PrimaryButton | typeof ToolbarPopover; +export type ToolbarButtonType = typeof ToolbarButton | typeof ToolbarPopover; /** Specific type for the toolbar children in its props */ interface NamedSlots { - primaryButton: ReactElement; + primaryButton: ReactElement; iconButtonGroup?: ReactElement; - extraButtons?: Array> | undefined; + extraButtons?: Array> | undefined; } /** diff --git a/packages/shared-ux/file/file_picker/impl/src/file_picker.stories.tsx b/packages/shared-ux/file/file_picker/impl/src/file_picker.stories.tsx index c314bfb1db65e..37e9a7758ab39 100644 --- a/packages/shared-ux/file/file_picker/impl/src/file_picker.stories.tsx +++ b/packages/shared-ux/file/file_picker/impl/src/file_picker.stories.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { ComponentMeta, ComponentStory } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { base64dLogo } from '@kbn/shared-ux-file-image-mocks'; -import type { FileImageMetadata, FileKind } from '@kbn/shared-ux-file-types'; +import type { FileImageMetadata, FileKindBrowser } from '@kbn/shared-ux-file-types'; import type { FileJSON, BaseFilesClient as FilesClient } from '@kbn/shared-ux-file-types'; import { FilesContext } from '@kbn/shared-ux-file-context'; import { FilePicker, Props as FilePickerProps } from './file_picker'; @@ -23,7 +23,7 @@ const getFileKind = (id: string) => id: kind, http: {}, allowedMimeTypes: ['*'], - } as FileKind); + } as FileKindBrowser); const defaultProps: FilePickerProps = { kind, diff --git a/packages/shared-ux/file/file_upload/impl/src/file_upload.stories.tsx b/packages/shared-ux/file/file_upload/impl/src/file_upload.stories.tsx index 652d4f618f4dc..8c01e47952b10 100644 --- a/packages/shared-ux/file/file_upload/impl/src/file_upload.stories.tsx +++ b/packages/shared-ux/file/file_upload/impl/src/file_upload.stories.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { ComponentMeta, ComponentStory } from '@storybook/react'; import { action } from '@storybook/addon-actions'; -import { FileKind, BaseFilesClient as FilesClient } from '@kbn/shared-ux-file-types'; +import { FileKindBrowser, BaseFilesClient as FilesClient } from '@kbn/shared-ux-file-types'; import { FilesContext } from '@kbn/shared-ux-file-context'; import { FileUpload, Props } from './file_upload'; @@ -37,7 +37,7 @@ const fileKinds = { allowedMimeTypes: ['application/zip'], }, }; -const getFileKind = (id: string) => (fileKinds as any)[id] as FileKind; +const getFileKind = (id: string) => (fileKinds as any)[id] as FileKindBrowser; const defaultArgs: Props = { kind, diff --git a/packages/shared-ux/file/file_upload/impl/src/upload_state.test.ts b/packages/shared-ux/file/file_upload/impl/src/upload_state.test.ts index 8fe9622fffc6e..644e826a7043d 100644 --- a/packages/shared-ux/file/file_upload/impl/src/upload_state.test.ts +++ b/packages/shared-ux/file/file_upload/impl/src/upload_state.test.ts @@ -9,7 +9,11 @@ import { DeeplyMockedKeys } from '@kbn/utility-types-jest'; import { of, delay, merge, tap, mergeMap } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; -import type { FileKind, FileJSON, BaseFilesClient as FilesClient } from '@kbn/shared-ux-file-types'; +import type { + FileKindBrowser, + FileJSON, + BaseFilesClient as FilesClient, +} from '@kbn/shared-ux-file-types'; import { createMockFilesClient } from '@kbn/shared-ux-file-mocks'; import { ImageMetadataFactory } from '@kbn/shared-ux-file-util'; @@ -29,7 +33,7 @@ describe('UploadState', () => { filesClient.create.mockReturnValue(of({ file: { id: 'test' } as FileJSON }) as any); filesClient.upload.mockReturnValue(of(undefined) as any); uploadState = new UploadState( - { id: 'test', http: {}, maxSizeBytes: 1000 } as FileKind, + { id: 'test', http: {}, maxSizeBytes: 1000 } as FileKindBrowser, filesClient, {}, imageMetadataFactory @@ -191,7 +195,7 @@ describe('UploadState', () => { it('option "allowRepeatedUploads" calls clear after upload is done', () => { testScheduler.run(({ expectObservable, cold }) => { uploadState = new UploadState( - { id: 'test', http: {}, maxSizeBytes: 1000 } as FileKind, + { id: 'test', http: {}, maxSizeBytes: 1000 } as FileKindBrowser, filesClient, { allowRepeatedUploads: true }, imageMetadataFactory diff --git a/packages/shared-ux/file/file_upload/impl/src/upload_state.ts b/packages/shared-ux/file/file_upload/impl/src/upload_state.ts index fc8a743c3d204..df8b7c79580f9 100644 --- a/packages/shared-ux/file/file_upload/impl/src/upload_state.ts +++ b/packages/shared-ux/file/file_upload/impl/src/upload_state.ts @@ -8,7 +8,11 @@ import * as Rx from 'rxjs'; import { ImageMetadataFactory, getImageMetadata, isImage } from '@kbn/shared-ux-file-util'; -import type { FileKind, FileJSON, BaseFilesClient as FilesClient } from '@kbn/shared-ux-file-types'; +import type { + FileKindBrowser, + FileJSON, + BaseFilesClient as FilesClient, +} from '@kbn/shared-ux-file-types'; import { i18nTexts } from './i18n_texts'; import { createStateSubject, type SimpleStateSubject, parseFileName } from './util'; @@ -48,7 +52,7 @@ export class UploadState { private subscriptions: Rx.Subscription[]; constructor( - private readonly fileKind: FileKind, + private readonly fileKind: FileKindBrowser, private readonly client: FilesClient, private readonly opts: UploadOptions = { allowRepeatedUploads: false }, private readonly loadImageMetadata: ImageMetadataFactory = getImageMetadata @@ -240,7 +244,7 @@ export const createUploadState = ({ imageMetadataFactory, ...options }: { - fileKind: FileKind; + fileKind: FileKindBrowser; client: FilesClient; imageMetadataFactory?: ImageMetadataFactory; } & UploadOptions) => { diff --git a/packages/shared-ux/file/types/README.md b/packages/shared-ux/file/types/README.md index 66e069f505928..c4fc97c25eff7 100644 --- a/packages/shared-ux/file/types/README.md +++ b/packages/shared-ux/file/types/README.md @@ -1,5 +1 @@ # @kbn/shared-ux-link-redirect-app-types - -To generate the types for the file client run. See ./build_file_client.ts - -`yarn ts-node ./packages/shared-ux/file/types/build_file_client.ts` diff --git a/packages/shared-ux/file/types/base_file_client.d.ts b/packages/shared-ux/file/types/base_file_client.ts similarity index 94% rename from packages/shared-ux/file/types/base_file_client.d.ts rename to packages/shared-ux/file/types/base_file_client.ts index 87805f63cfc39..4a00f2de00516 100644 --- a/packages/shared-ux/file/types/base_file_client.d.ts +++ b/packages/shared-ux/file/types/base_file_client.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import type { FileJSON, FileKind } from '.'; +import type { FileShareJSON, FileShareJSONWithToken } from './sharing'; +import type { FileJSON, FileKindBase } from '.'; export interface Pagination { page?: number; @@ -62,7 +63,7 @@ export interface BaseFilesClient { */ getById: (args: { id: string; kind: string } & Abortable) => Promise<{ file: FileJSON }>; /** - * List all file objects, of a given {@link FileKind}. + * List all file objects, of a given {@link FileKindBrowser}. * * @param args - list files args */ @@ -154,5 +155,5 @@ export interface BaseFilesClient { * Get a file kind * @param id The id of the file kind */ - getFileKind: (id: string) => FileKind; + getFileKind: (id: string) => FileKindBase; } diff --git a/packages/shared-ux/file/types/index.d.ts b/packages/shared-ux/file/types/index.ts similarity index 77% rename from packages/shared-ux/file/types/index.d.ts rename to packages/shared-ux/file/types/index.ts index 9d63635179ca5..4c49124f7149f 100644 --- a/packages/shared-ux/file/types/index.d.ts +++ b/packages/shared-ux/file/types/index.ts @@ -7,6 +7,7 @@ */ export type { BaseFilesClient, Abortable, Pagination } from './base_file_client'; +export type { FileShare, FileShareJSON, FileShareJSONWithToken } from './sharing'; /* Status of a file. * @@ -23,19 +24,6 @@ export type FileStatus = 'AWAITING_UPLOAD' | 'UPLOADING' | 'READY' | 'UPLOAD_ERR */ export type FileCompression = 'br' | 'gzip' | 'deflate' | 'none'; -/** Definition for an endpoint that the File's service will generate */ -interface HttpEndpointDefinition { - /** - * Specify the tags for this endpoint. - * - * @example - * // This will enable access control to this endpoint for users that can access "myApp" only. - * { tags: ['access:myApp'] } - * - */ - tags: string[]; -} - /** * File metadata fields are defined per the ECS specification: * @@ -240,23 +228,11 @@ export interface FileJSON { user?: FileMetadata['user']; } -/* - * A descriptor of meta values associated with a set or "kind" of files. - * - * @note In order to use the file service consumers must register a {@link FileKind} - * in the {@link FileKindsRegistry}. - */ -export interface FileKind { +export interface FileKindBase { /** * Unique file kind ID */ id: string; - /** - * Maximum size, in bytes, a file of this kind can be. - * - * @default 4MiB - */ - maxSizeBytes?: number; /** * The MIME type of the file content. @@ -264,52 +240,16 @@ export interface FileKind { * @default accept all mime types */ allowedMimeTypes?: string[]; +} +export interface FileKindBrowser extends FileKindBase { /** - * Blob store specific settings that enable configuration of storage - * details. - */ - blobStoreSettings?: BlobStorageSettings; - - /** - * Specify which HTTP routes to create for the file kind. + * Max file contents size, in bytes, enforced for this file kind in the upload + * component. * - * You can always create your own HTTP routes for working with files but - * this interface allows you to expose basic CRUD operations, upload, download - * and sharing of files over a RESTful-like interface. - * - * @note The public {@link FileClient} uses these endpoints. + * @default 4MiB */ - http: { - /** - * Expose file creation (and upload) over HTTP. - */ - create?: HttpEndpointDefinition; - /** - * Expose file updates over HTTP. - */ - update?: HttpEndpointDefinition; - /** - * Expose file deletion over HTTP. - */ - delete?: HttpEndpointDefinition; - /** - * Expose "get by ID" functionality over HTTP. - */ - getById?: HttpEndpointDefinition; - /** - * Expose the ability to list all files of this kind over HTTP. - */ - list?: HttpEndpointDefinition; - /** - * Expose the ability to download a file's contents over HTTP. - */ - download?: HttpEndpointDefinition; - /** - * Expose file share functionality over HTTP. - */ - share?: HttpEndpointDefinition; - }; + maxSizeBytes?: number; } /** diff --git a/packages/shared-ux/file/types/sharing.ts b/packages/shared-ux/file/types/sharing.ts new file mode 100644 index 0000000000000..083a6e9b111f5 --- /dev/null +++ b/packages/shared-ux/file/types/sharing.ts @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * Data stored with a file share object + */ +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type FileShare = { + /** + * ISO timestamp of when the file share was created. + */ + created: string; + + /** + * Secret token used to access the associated file. + */ + token: string; + + /** + * Human friendly name for this share token. + */ + name?: string; + + /** + * The unix timestamp (in milliseconds) this file share will expire. + * + * TODO: in future we could add a special value like "forever", but this should + * not be the default. + */ + valid_until: number; +}; + +/** + * Attributes of a file that represent a serialised version of the file. + */ +export interface FileShareJSON { + /** + * Unique ID share instance + */ + id: string; + /** + * ISO timestamp the share was created + */ + created: FileShare['created']; + /** + * Unix timestamp (in milliseconds) of when this share expires + */ + validUntil: FileShare['valid_until']; + /** + * A user-friendly name for the file share + */ + name?: FileShare['name']; + /** + * The ID of the file this share is linked to + */ + fileId: string; +} + +/** + * A version of the file share with a token included. + * + * @note This should only be shown when the file share is first created + */ +export type FileShareJSONWithToken = FileShareJSON & { + /** + * Secret token that can be used to access files + */ + token: string; +}; diff --git a/packages/shared-ux/file/types/tsconfig.json b/packages/shared-ux/file/types/tsconfig.json index 1e6c78a051db3..fef75d832cab6 100644 --- a/packages/shared-ux/file/types/tsconfig.json +++ b/packages/shared-ux/file/types/tsconfig.json @@ -7,7 +7,7 @@ ], }, "include": [ - "*.d.ts" + "*.ts" ], "exclude": [ "target/**/*", diff --git a/src/core/server/integration_tests/saved_objects/migrations/archives/1m_dummy_so.zip b/src/core/server/integration_tests/saved_objects/migrations/archives/1m_dummy_so.zip new file mode 100644 index 0000000000000..18b34d8b1ccb3 Binary files /dev/null and b/src/core/server/integration_tests/saved_objects/migrations/archives/1m_dummy_so.zip differ diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/batch_size_bytes.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/batch_size_bytes.test.ts index f2296d41d905e..17a628d32e1d8 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/batch_size_bytes.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/batch_size_bytes.test.ts @@ -118,7 +118,7 @@ describe('migration v2', () => { await root.preboot(); await root.setup(); await expect(root.start()).rejects.toMatchInlineSnapshot( - `[Error: Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715329 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.]` + `[Error: Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715272 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.]` ); await retryAsync( @@ -131,7 +131,7 @@ describe('migration v2', () => { expect( records.find((rec) => rec.message.startsWith( - `Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715329 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.` + `Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715272 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.` ) ) ).toBeDefined(); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index 7d9e4bae782e2..14569a91dbb98 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -126,7 +126,7 @@ describe('checking migration metadata changes on all registered SO types', () => "rules-settings": "9854495c3b54b16a6625fb250c35e5504da72266", "sample-data-telemetry": "c38daf1a49ed24f2a4fb091e6e1e833fccf19935", "search": "01bc42d635e9ea0588741c4c7a2bbd3feb3ac5dc", - "search-session": "5f40f6101fc2ec8ce5210d735ea2e00a87c02886", + "search-session": "58a44d14ec991739166b2ec28d718001ab0f4b28", "search-telemetry": "ab67ef721f294f28d5e10febbd20653347720188", "security-rule": "1ff82dfb2298c3caf6888fc3ef15c6bf7a628877", "security-solution-signals-migration": "c2db409c1857d330beb3d6fd188fa186f920302c", diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts index 7845ec72ab2ec..691800feee0e3 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts @@ -43,6 +43,7 @@ import { type DocumentsTransformFailed, type DocumentsTransformSuccess, MIGRATION_CLIENT_OPTIONS, + createBulkIndexOperationTuple, } from '@kbn/core-saved-objects-migration-server-internal'; const { startES } = createTestServers({ @@ -78,7 +79,7 @@ describe('migration actions', () => { }, }, })(); - const sourceDocs = [ + const docs = [ { _source: { title: 'doc 1' } }, { _source: { title: 'doc 2' } }, { _source: { title: 'doc 3' } }, @@ -88,7 +89,7 @@ describe('migration actions', () => { await bulkOverwriteTransformedDocuments({ client, index: 'existing_index_with_docs', - transformedDocs: sourceDocs, + operations: docs.map(createBulkIndexOperationTuple), refresh: 'wait_for', })(); @@ -101,7 +102,7 @@ describe('migration actions', () => { await bulkOverwriteTransformedDocuments({ client, index: 'existing_index_with_write_block', - transformedDocs: sourceDocs, + operations: docs.map(createBulkIndexOperationTuple), refresh: 'wait_for', })(); await setWriteBlock({ client, index: 'existing_index_with_write_block' })(); @@ -302,7 +303,7 @@ describe('migration actions', () => { const res = (await bulkOverwriteTransformedDocuments({ client, index: 'new_index_without_write_block', - transformedDocs: sourceDocs, + operations: sourceDocs.map(createBulkIndexOperationTuple), refresh: 'wait_for', })()) as Either.Left; @@ -882,7 +883,7 @@ describe('migration actions', () => { await bulkOverwriteTransformedDocuments({ client, index: 'reindex_target_4', - transformedDocs: sourceDocs, + operations: sourceDocs.map(createBulkIndexOperationTuple), refresh: 'wait_for', })(); @@ -1441,7 +1442,7 @@ describe('migration actions', () => { await bulkOverwriteTransformedDocuments({ client, index: 'existing_index_without_mappings', - transformedDocs: sourceDocs, + operations: sourceDocs.map(createBulkIndexOperationTuple), refresh: 'wait_for', })(); @@ -1837,7 +1838,7 @@ describe('migration actions', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'existing_index_with_docs', - transformedDocs: newDocs, + operations: newDocs.map(createBulkIndexOperationTuple), refresh: 'wait_for', }); @@ -1860,10 +1861,10 @@ describe('migration actions', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'existing_index_with_docs', - transformedDocs: [ + operations: [ ...existingDocs, { _source: { title: 'doc 8' } } as unknown as SavedObjectsRawDoc, - ], + ].map(createBulkIndexOperationTuple), refresh: 'wait_for', }); await expect(task()).resolves.toMatchInlineSnapshot(` @@ -1883,7 +1884,7 @@ describe('migration actions', () => { bulkOverwriteTransformedDocuments({ client, index: 'existing_index_with_write_block', - transformedDocs: newDocs, + operations: newDocs.map(createBulkIndexOperationTuple), refresh: 'wait_for', })() ).resolves.toMatchInlineSnapshot(` @@ -1906,7 +1907,7 @@ describe('migration actions', () => { const task = bulkOverwriteTransformedDocuments({ client, index: 'existing_index_with_docs', - transformedDocs: newDocs, + operations: newDocs.map(createBulkIndexOperationTuple), }); await expect(task()).resolves.toMatchInlineSnapshot(` Object { diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.fixtures.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.fixtures.ts new file mode 100644 index 0000000000000..7d605cf116341 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.fixtures.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SavedObjectsBulkCreateObject } from '@kbn/core-saved-objects-api-server'; +import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; + +const defaultType: SavedObjectsType = { + name: 'defaultType', + hidden: false, + namespaceType: 'agnostic', + mappings: { + properties: { + name: { type: 'keyword' }, + }, + }, + migrations: {}, +}; + +export const baselineTypes: Array> = [ + { + ...defaultType, + name: 'server', + }, + { + ...defaultType, + name: 'basic', + }, + { + ...defaultType, + name: 'deprecated', + }, + { + ...defaultType, + name: 'complex', + mappings: { + properties: { + name: { type: 'text' }, + value: { type: 'integer' }, + }, + }, + excludeOnUpgrade: () => { + return { + bool: { + must: [{ term: { type: 'complex' } }, { range: { 'complex.value': { lte: 1 } } }], + }, + }; + }, + }, +]; + +export const baselineDocuments: SavedObjectsBulkCreateObject[] = [ + ...['server-foo', 'server-bar', 'server-baz'].map((name) => ({ + type: 'server', + attributes: { + name, + }, + })), + ...['basic-foo', 'basic-bar', 'basic-baz'].map((name) => ({ + type: 'basic', + attributes: { + name, + }, + })), + ...['deprecated-foo', 'deprecated-bar', 'deprecated-baz'].map((name) => ({ + type: 'deprecated', + attributes: { + name, + }, + })), + ...['complex-foo', 'complex-bar', 'complex-baz', 'complex-lipsum'].map((name, index) => ({ + type: 'complex', + attributes: { + name, + value: index, + }, + })), +]; diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts new file mode 100644 index 0000000000000..80681ffd0a5af --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts @@ -0,0 +1,335 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import fs from 'fs/promises'; +import { SemVer } from 'semver'; +import { Env } from '@kbn/config'; +import type { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { getEnvOptions } from '@kbn/config-mocks'; +import { REPO_ROOT } from '@kbn/repo-info'; +import { createTestServers, type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; +import { getKibanaMigratorTestKit } from '../kibana_migrator_test_kit'; +import { baselineDocuments, baselineTypes } from './active_delete.fixtures'; +import { delay } from '../test_utils'; + +const kibanaIndex = '.kibana_migrator_tests'; +export const logFilePath = Path.join(__dirname, 'active_delete.test.log'); +const currentVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version; +const nextMinor = new SemVer(currentVersion).inc('minor').format(); + +describe('when upgrading to a new stack version', () => { + let esServer: TestElasticsearchUtils['es']; + let esClient: ElasticsearchClient; + + const startElasticsearch = async () => { + const { startES } = createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), + settings: { + es: { + license: 'basic', + }, + }, + }); + return await startES(); + }; + + const createBaseline = async () => { + const { client, runMigrations, savedObjectsRepository } = await getKibanaMigratorTestKit({ + kibanaIndex, + types: baselineTypes, + }); + + await runMigrations(); + + await savedObjectsRepository.bulkCreate(baselineDocuments, { + refresh: 'wait_for', + }); + + return client; + }; + + beforeAll(async () => { + esServer = await startElasticsearch(); + }); + + afterAll(async () => { + await esServer?.stop(); + await delay(10); + }); + + describe('and the mappings match (diffMappings() === false)', () => { + describe('and discardUnknownObjects = true', () => { + let indexContents: SearchResponse<{ type: string }, Record>; + + beforeAll(async () => { + esClient = await createBaseline(); + + await fs.unlink(logFilePath).catch(() => {}); + // remove the 'deprecated' type from the mappings, so that it is considered unknown + const types = baselineTypes.filter((type) => type.name !== 'deprecated'); + const { client, runMigrations } = await getKibanaMigratorTestKit({ + settings: { + migrations: { + discardUnknownObjects: nextMinor, + }, + }, + kibanaIndex, + types, + kibanaVersion: nextMinor, + logFilePath, + }); + + await runMigrations(); + + indexContents = await client.search({ index: kibanaIndex, size: 100 }); + }); + + afterAll(async () => { + await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + }); + + it('the migrator is skipping reindex operation and executing CLEANUP_UNKNOWN_AND_EXCLUDED step', async () => { + const logs = await fs.readFile(logFilePath, 'utf-8'); + expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).toMatch( + '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED' + ); + // we gotta inform that we are deleting unknown documents too (discardUnknownObjects: true) + expect(logs).toMatch( + '[.kibana_migrator_tests] Kibana has been configured to discard unknown documents for this migration.' + ); + + expect(logs).toMatch( + 'Therefore, the following documents with unknown types will not be taken into account and they will not be available after the migration:' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS' + ); + expect(logs).toMatch('[.kibana_migrator_tests] CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); + }); + + describe('CLEANUP_UNKNOWN_AND_EXCLUDED', () => { + it('preserves documents with known types', async () => { + const basicDocumentCount = indexContents.hits.hits.filter( + (result) => result._source?.type === 'basic' + ).length; + + expect(basicDocumentCount).toEqual(3); + }); + + it('deletes documents with unknown types', async () => { + const deprecatedDocumentCount = indexContents.hits.hits.filter( + (result) => result._source?.type === 'deprecated' + ).length; + + expect(deprecatedDocumentCount).toEqual(0); + }); + + it('deletes documents that belong to REMOVED_TYPES', async () => { + const serverDocumentCount = indexContents.hits.hits.filter( + (result) => result._source?.type === 'server' + ).length; + + expect(serverDocumentCount).toEqual(0); + }); + + it("deletes documents that have been excludeOnUpgrade'd via plugin hook", async () => { + const complexDocuments = indexContents.hits.hits.filter( + (result) => result._source?.type === 'complex' + ); + + expect(complexDocuments.length).toEqual(2); + expect(complexDocuments[0]._source).toEqual( + expect.objectContaining({ + complex: { + name: 'complex-baz', + value: 2, + }, + type: 'complex', + }) + ); + expect(complexDocuments[1]._source).toEqual( + expect.objectContaining({ + complex: { + name: 'complex-lipsum', + value: 3, + }, + type: 'complex', + }) + ); + }); + }); + }); + + describe('and discardUnknownObjects = false', () => { + beforeAll(async () => { + esClient = await createBaseline(); + }); + afterAll(async () => { + await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + }); + beforeEach(async () => { + await fs.unlink(logFilePath).catch(() => {}); + }); + + it('fails if unknown documents exist', async () => { + // remove the 'deprecated' type from the mappings, so that SO of this type are considered unknown + const types = baselineTypes.filter((type) => type.name !== 'deprecated'); + const { runMigrations } = await getKibanaMigratorTestKit({ + kibanaIndex, + types, + kibanaVersion: nextMinor, + logFilePath, + }); + + try { + await runMigrations(); + } catch (err) { + const errorMessage = err.message; + expect(errorMessage).toMatch( + 'Unable to complete saved object migrations for the [.kibana_migrator_tests] index: Migration failed because some documents were found which use unknown saved object types:' + ); + expect(errorMessage).toMatch( + 'To proceed with the migration you can configure Kibana to discard unknown saved objects for this migration.' + ); + expect(errorMessage).toMatch(/deprecated:.*\(type: "deprecated"\)/); + } + + const logs = await fs.readFile(logFilePath, 'utf-8'); + expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).toMatch( + '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED' + ); + expect(logs).toMatch('[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED -> FATAL'); + }); + + it('proceeds if there are no unknown documents', async () => { + const { client, runMigrations } = await getKibanaMigratorTestKit({ + kibanaIndex, + types: baselineTypes, + kibanaVersion: nextMinor, + logFilePath, + }); + + await runMigrations(); + + const logs = await fs.readFile(logFilePath, 'utf-8'); + expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).toMatch( + '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS' + ); + expect(logs).toMatch('[.kibana_migrator_tests] CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); + + const indexContents = await client.search({ index: kibanaIndex, size: 100 }); + + expect(indexContents.hits.hits.length).toEqual(8); + }); + }); + }); + + describe('and the mappings do NOT match (diffMappings() === true)', () => { + beforeAll(async () => { + esClient = await createBaseline(); + }); + afterAll(async () => { + await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + }); + beforeEach(async () => { + await fs.unlink(logFilePath).catch(() => {}); + }); + + it('the migrator does not skip reindexing', async () => { + const incompatibleTypes: Array> = baselineTypes.map((type) => { + if (type.name === 'complex') { + return { + ...type, + mappings: { + properties: { + name: { type: 'keyword' }, // text => keyword + value: { type: 'long' }, // integer => long + }, + }, + }; + } else { + return type; + } + }); + + const { client, runMigrations } = await getKibanaMigratorTestKit({ + kibanaIndex, + types: incompatibleTypes, + kibanaVersion: nextMinor, + logFilePath, + }); + + await runMigrations(); + + const logs = await fs.readFile(logFilePath, 'utf-8'); + expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).toMatch( + '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CHECK_UNKNOWN_DOCUMENTS.' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK.' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.' + ); + expect(logs).toMatch( + '[.kibana_migrator_tests] CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY.' + ); + expect(logs).toMatch('[.kibana_migrator_tests] MARK_VERSION_INDEX_READY -> DONE'); + + const indexContents: SearchResponse< + { type: string }, + Record + > = await client.search({ index: kibanaIndex, size: 100 }); + + expect(indexContents.hits.hits.length).toEqual(8); // we're removing a couple of 'complex' (value < = 1) + + // double-check that the deprecated documents have not been deleted + const deprecatedDocumentCount = indexContents.hits.hits.filter( + (result) => result._source?.type === 'deprecated' + ).length; + expect(deprecatedDocumentCount).toEqual(3); + }); + }); +}); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete_multiple_instances.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete_multiple_instances.test.ts new file mode 100644 index 0000000000000..57e4844ef3182 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete_multiple_instances.test.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import fs from 'fs/promises'; +import { SemVer } from 'semver'; +import { Env } from '@kbn/config'; +import { getEnvOptions } from '@kbn/config-mocks'; +import { REPO_ROOT } from '@kbn/repo-info'; +import { type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { SavedObjectsBulkCreateObject } from '@kbn/core-saved-objects-api-server'; +import { + defaultLogFilePath, + getEsClient, + getKibanaMigratorTestKit, + startElasticsearch, +} from '../kibana_migrator_test_kit'; +import { baselineTypes } from './active_delete.fixtures'; +import { delay } from '../test_utils'; +import { createBaselineArchive } from '../kibana_migrator_archive_utils'; + +const PARALLEL_MIGRATORS = 6; +const DOCUMENTS_PER_TYPE = 250000; + +const kibanaIndex = '.kibana_migrator_tests'; +const currentVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version; +const nextMinor = new SemVer(currentVersion).inc('minor').format(); + +const dataArchive = Path.join(__dirname, '..', 'archives', '1m_dummy_so.zip'); + +jest.setTimeout(24 * 3600 * 100); + +describe('multiple migrator instances running in parallel', () => { + it.skip('enable and focus this test (it.skip => fit), and run it, in order to create a baseline archive', async () => { + // generate DOCUMENTS_PER_TYPE documents of each type + const documents: SavedObjectsBulkCreateObject[] = ['server', 'basic', 'deprecated', 'complex'] + .map((type) => + new Array(DOCUMENTS_PER_TYPE).fill(true).map((_, index) => ({ + type, + attributes: { + name: `${type}-${++index}`, + ...(type === 'complex' && { value: index }), + }, + })) + ) + .flat(); + + await createBaselineArchive({ kibanaIndex, types: baselineTypes, documents, dataArchive }); + }); + + describe('when upgrading to a new stack version with matching mappings', () => { + let esServer: TestElasticsearchUtils['es']; + let esClient: ElasticsearchClient; + beforeAll(async () => { + esServer = await startElasticsearch({ dataArchive }); + esClient = await getEsClient(); + await fs.unlink(defaultLogFilePath).catch(() => {}); + + for (let i = 0; i < PARALLEL_MIGRATORS; ++i) { + await fs.unlink(Path.join(__dirname, `active_delete_instance_${i}.log`)).catch(() => {}); + } + }); + + it('will actively delete and successfully complete migration', async () => { + const startTime = Date.now(); + const types = baselineTypes + .filter((type) => type.name !== 'deprecated') + .map((type) => { + if (type.name !== 'complex') { + return type; + } + + return { + ...type, + excludeOnUpgrade: () => { + return { + bool: { + must: [ + { term: { type: 'complex' } }, + { range: { 'complex.value': { lte: 125000 } } }, + ], + }, + }; + }, + }; + }); + + const beforeCleanup = await getAggregatedTypesCount(); + expect(beforeCleanup.server).toEqual(DOCUMENTS_PER_TYPE); + expect(beforeCleanup.basic).toEqual(DOCUMENTS_PER_TYPE); + expect(beforeCleanup.deprecated).toEqual(DOCUMENTS_PER_TYPE); + expect(beforeCleanup.complex).toEqual(DOCUMENTS_PER_TYPE); + + const testKits = await Promise.all( + new Array(PARALLEL_MIGRATORS) + .fill({ + settings: { + migrations: { + discardUnknownObjects: nextMinor, + }, + }, + kibanaIndex, + types, + kibanaVersion: nextMinor, + }) + .map((config, index) => + getKibanaMigratorTestKit({ + ...config, + logFilePath: Path.join(__dirname, `active_delete_instance_${index}.log`), + }) + ) + ); + + const results = await Promise.all(testKits.map((testKit) => testKit.runMigrations())); + expect(results.flat().every((result) => result.status === 'migrated')).toEqual(true); + + for (let i = 0; i < PARALLEL_MIGRATORS; ++i) { + const logs = await fs.readFile( + Path.join(__dirname, `active_delete_instance_${i}.log`), + 'utf-8' + ); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); + expect(logs).toMatch('Migration completed'); + } + + const endTime = Date.now(); + // eslint-disable-next-line no-console + console.debug(`Migration took: ${(endTime - startTime) / 1000} seconds`); + + // After cleanup + const afterCleanup = await getAggregatedTypesCount(); + expect(afterCleanup.server).not.toBeDefined(); // 'server' is part of the REMOVED_TYPES + expect(afterCleanup.basic).toEqual(DOCUMENTS_PER_TYPE); // we keep 'basic' SOs + expect(afterCleanup.deprecated).not.toBeDefined(); // 'deprecated' is no longer present in nextMinor's mappings + expect(afterCleanup.complex).toEqual(DOCUMENTS_PER_TYPE / 2); // we excludeFromUpgrade half of them with a hook + }); + + afterAll(async () => { + // await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + await esServer?.stop(); + await delay(10); + }); + + const getAggregatedTypesCount = async () => { + await esClient.indices.refresh(); + const response = await esClient.search({ + index: kibanaIndex, + _source: false, + aggs: { + typesAggregation: { + terms: { + // assign type __UNKNOWN__ to those documents that don't define one + missing: '__UNKNOWN__', + field: 'type', + size: 10, + }, + aggs: { + docs: { + top_hits: { + size: 2, + _source: { + excludes: ['*'], + }, + }, + }, + }, + }, + }, + }); + + return (response.aggregations!.typesAggregation.buckets as unknown as any).reduce( + (acc: any, current: any) => { + acc[current.key] = current.doc_count; + return acc; + }, + {} + ); + }; + }); +}); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts index a6060b166335f..aa5d1c0c06eb4 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts @@ -64,7 +64,13 @@ describe('skip reindexing', () => { logs = await fs.readFile(logFilePath, 'utf-8'); expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); - expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> PREPARE_COMPATIBLE_MIGRATION'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED'); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' + ); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' + ); expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT'); expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS'); expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); @@ -87,7 +93,7 @@ describe('skip reindexing', () => { logs = await fs.readFile(logFilePath, 'utf-8'); expect(logs).toMatch('INIT -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT'); - expect(logs).not.toMatch('INIT -> PREPARE_COMPATIBLE_MIGRATION'); + expect(logs).not.toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); }); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_archive_utils.ts b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_archive_utils.ts new file mode 100644 index 0000000000000..88342c1a66ac3 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_archive_utils.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +/* eslint-disable no-console */ + +import Path from 'path'; +import { exec } from 'child_process'; +import { promisify } from 'util'; +const execPromise = promisify(exec); + +import { SavedObjectsBulkCreateObject } from '@kbn/core-saved-objects-api-server'; +import { SavedObjectsType } from '@kbn/core-saved-objects-server'; +import { getKibanaMigratorTestKit, startElasticsearch } from './kibana_migrator_test_kit'; +import { delay } from './test_utils'; + +const DEFAULT_BATCH_SIZE = 100000; + +interface CreateBaselineArchiveParams { + kibanaIndex: string; + types: Array>; + documents: SavedObjectsBulkCreateObject[]; + batchSize?: number; + esBaseFolder?: string; + dataArchive: string; +} + +export const createBaselineArchive = async ({ + types, + documents, + kibanaIndex, + batchSize = DEFAULT_BATCH_SIZE, + esBaseFolder = Path.join(__dirname, `target`), + dataArchive, +}: CreateBaselineArchiveParams) => { + const startTime = Date.now(); + const esServer = await startElasticsearch({ basePath: esBaseFolder }); + + const { runMigrations, savedObjectsRepository } = await getKibanaMigratorTestKit({ + kibanaIndex, + types, + }); + + await runMigrations(); + + const batches = Math.ceil(documents.length / batchSize); + + for (let i = 0; i < batches; ++i) { + console.log(`Indexing up to ${batchSize} docs (batch ${i + 1} of ${batches})`); + await savedObjectsRepository.bulkCreate(documents.slice(batchSize * i, batchSize * (i + 1)), { + refresh: 'wait_for', + }); + } + + await compressBaselineArchive(esBaseFolder, dataArchive); + console.log(`Archive created in: ${(Date.now() - startTime) / 1000} seconds`, dataArchive); + await delay(200); + await esServer.stop(); + // await fs.rm(esBaseFolder, { recursive: true }); +}; + +const compressBaselineArchive = async (esFolder: string, archiveFile: string) => { + const dataFolder = Path.join(esFolder, 'es-test-cluster'); + const cmd = `cd ${dataFolder} && zip -r ${archiveFile} data -x ".DS_Store" -x "__MACOSX"`; + await execPromise(cmd); +}; diff --git a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts new file mode 100644 index 0000000000000..df3cce7dbdca6 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts @@ -0,0 +1,274 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import { defaultsDeep } from 'lodash'; +import { BehaviorSubject, firstValueFrom, map } from 'rxjs'; +import { ConfigService, Env } from '@kbn/config'; +import { getEnvOptions } from '@kbn/config-mocks'; +import { REPO_ROOT } from '@kbn/repo-info'; +import { KibanaMigrator } from '@kbn/core-saved-objects-migration-server-internal'; + +import { + SavedObjectConfig, + type SavedObjectsConfigType, + type SavedObjectsMigrationConfigType, + SavedObjectTypeRegistry, + IKibanaMigrator, + MigrationResult, +} from '@kbn/core-saved-objects-base-server-internal'; +import { SavedObjectsRepository } from '@kbn/core-saved-objects-api-server-internal'; +import { + ElasticsearchConfig, + type ElasticsearchConfigType, +} from '@kbn/core-elasticsearch-server-internal'; +import { AgentManager, configureClient } from '@kbn/core-elasticsearch-client-server-internal'; +import { type LoggingConfigType, LoggingSystem } from '@kbn/core-logging-server-internal'; + +import type { ISavedObjectTypeRegistry, SavedObjectsType } from '@kbn/core-saved-objects-server'; +import { esTestConfig, kibanaServerTestUser } from '@kbn/test'; +import { LoggerFactory } from '@kbn/logging'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { registerServiceConfig } from '@kbn/core-root-server-internal'; +import { ISavedObjectsRepository } from '@kbn/core-saved-objects-api-server'; +import { getDocLinks, getDocLinksMeta } from '@kbn/doc-links'; +import { DocLinksServiceStart } from '@kbn/core-doc-links-server'; +import { createTestServers } from '@kbn/core-test-helpers-kbn-server'; + +export const defaultLogFilePath = Path.join(__dirname, 'kibana_migrator_test_kit.log'); + +const env = Env.createDefault(REPO_ROOT, getEnvOptions()); +// Extract current stack version from Env, to use as a default +const currentVersion = env.packageInfo.version; +const currentBranch = env.packageInfo.branch; + +export interface GetEsClientParams { + settings?: Record; + kibanaVersion?: string; + logFilePath?: string; +} + +export interface KibanaMigratorTestKitParams { + kibanaIndex?: string; + kibanaVersion?: string; + kibanaBranch?: string; + settings?: Record; + types?: Array>; + logFilePath?: string; +} + +export interface KibanaMigratorTestKit { + client: ElasticsearchClient; + migrator: IKibanaMigrator; + runMigrations: (rerun?: boolean) => Promise; + typeRegistry: ISavedObjectTypeRegistry; + savedObjectsRepository: ISavedObjectsRepository; +} + +export const startElasticsearch = async ({ + basePath, + dataArchive, +}: { + basePath?: string; + dataArchive?: string; +}) => { + const { startES } = createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), + settings: { + es: { + license: 'basic', + basePath, + dataArchive, + }, + }, + }); + return await startES(); +}; + +export const getEsClient = async ({ + settings = {}, + kibanaVersion = currentVersion, + logFilePath = defaultLogFilePath, +}: GetEsClientParams = {}) => { + const loggingSystem = new LoggingSystem(); + const loggerFactory = loggingSystem.asLoggerFactory(); + + const configService = getConfigService(settings, loggerFactory, logFilePath); + + // configure logging system + const loggingConf = await firstValueFrom(configService.atPath('logging')); + loggingSystem.upgrade(loggingConf); + + return await getElasticsearchClient(configService, loggerFactory, kibanaVersion); +}; + +export const getKibanaMigratorTestKit = async ({ + settings = {}, + kibanaIndex = '.kibana', + kibanaVersion = currentVersion, + kibanaBranch = currentBranch, + types = [], + logFilePath = defaultLogFilePath, +}: KibanaMigratorTestKitParams = {}): Promise => { + const loggingSystem = new LoggingSystem(); + const loggerFactory = loggingSystem.asLoggerFactory(); + + const configService = getConfigService(settings, loggerFactory, logFilePath); + + // configure logging system + const loggingConf = await firstValueFrom(configService.atPath('logging')); + loggingSystem.upgrade(loggingConf); + + const client = await getElasticsearchClient(configService, loggerFactory, kibanaVersion); + + const typeRegistry = new SavedObjectTypeRegistry(); + + // types must be registered before instantiating the migrator + registerTypes(typeRegistry, types); + + const migrator = await getMigrator( + configService, + client, + typeRegistry, + loggerFactory, + kibanaIndex, + kibanaVersion, + kibanaBranch + ); + + const runMigrations = async (rerun?: boolean) => { + migrator.prepareMigrations(); + return await migrator.runMigrations({ rerun }); + }; + + const savedObjectsRepository = SavedObjectsRepository.createRepository( + migrator, + typeRegistry, + kibanaIndex, + client, + loggerFactory.get('saved_objects') + ); + + return { + client, + migrator, + runMigrations, + typeRegistry, + savedObjectsRepository, + }; +}; + +const getConfigService = ( + settings: Record, + loggerFactory: LoggerFactory, + logFilePath: string +) => { + // Define some basic default kibana settings + const DEFAULTS_SETTINGS = { + server: { + autoListen: true, + // Use the ephemeral port to make sure that tests use the first available + // port and aren't affected by the timing issues in test environment. + port: 0, + xsrf: { disableProtection: true }, + }, + elasticsearch: { + hosts: [esTestConfig.getUrl()], + username: kibanaServerTestUser.username, + password: kibanaServerTestUser.password, + }, + logging: { + appenders: { + file: { + type: 'file', + fileName: logFilePath, + layout: { + type: 'json', + }, + }, + }, + loggers: [ + { + name: 'root', + level: 'info', + appenders: ['file'], + }, + ], + }, + plugins: {}, + migrations: { skip: false }, + }; + + const rawConfigProvider = { + getConfig$: () => new BehaviorSubject(defaultsDeep({}, settings, DEFAULTS_SETTINGS)), + }; + + const configService = new ConfigService(rawConfigProvider, env, loggerFactory); + registerServiceConfig(configService); + return configService; +}; + +const getElasticsearchClient = async ( + configService: ConfigService, + loggerFactory: LoggerFactory, + kibanaVersion: string +) => { + const esClientConfig = await firstValueFrom( + configService + .atPath('elasticsearch') + .pipe(map((rawConfig) => new ElasticsearchConfig(rawConfig))) + ); + + return configureClient(esClientConfig, { + logger: loggerFactory.get('elasticsearch'), + type: 'data', + agentFactoryProvider: new AgentManager(), + kibanaVersion, + }); +}; + +const getMigrator = async ( + configService: ConfigService, + client: ElasticsearchClient, + typeRegistry: ISavedObjectTypeRegistry, + loggerFactory: LoggerFactory, + kibanaIndex: string, + kibanaVersion: string, + kibanaBranch: string +) => { + const savedObjectsConf = await firstValueFrom( + configService.atPath('savedObjects') + ); + const savedObjectsMigrationConf = await firstValueFrom( + configService.atPath('migrations') + ); + const soConfig = new SavedObjectConfig(savedObjectsConf, savedObjectsMigrationConf); + + const docLinks: DocLinksServiceStart = { + ...getDocLinksMeta({ kibanaBranch }), + links: getDocLinks({ kibanaBranch }), + }; + + return new KibanaMigrator({ + client, + typeRegistry, + kibanaIndex, + soMigrationsConfig: soConfig.migration, + kibanaVersion, + logger: loggerFactory.get('savedobjects-service'), + docLinks, + waitForMigrationCompletion: false, // ensure we have an active role in the migration + }); +}; + +const registerTypes = ( + typeRegistry: SavedObjectTypeRegistry, + types?: Array> +) => { + (types || []).forEach((type) => typeRegistry.registerType(type)); +}; diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json index 1791e14334243..d1c69ad2d1e49 100644 --- a/src/core/tsconfig.json +++ b/src/core/tsconfig.json @@ -148,6 +148,7 @@ "@kbn/core-lifecycle-browser", "@kbn/core-custom-branding-browser", "@kbn/core-custom-branding-server", + "@kbn/core-elasticsearch-client-server-internal", ], "exclude": [ "target/**/*", diff --git a/src/dev/eslint/security_eslint_rule_tests.ts b/src/dev/eslint/security_eslint_rule_tests.ts new file mode 100644 index 0000000000000..eac946ebe4b25 --- /dev/null +++ b/src/dev/eslint/security_eslint_rule_tests.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as a from 'lodash'; // eslint-disable-line no-restricted-imports +import * as b from 'lodash/fp'; // eslint-disable-line no-restricted-imports + +import { set as c } from 'lodash'; // eslint-disable-line no-restricted-imports +import { setWith as d } from 'lodash'; // eslint-disable-line no-restricted-imports +import { template as e } from 'lodash'; // eslint-disable-line no-restricted-imports + +// The following import statements can't be tested because they are not in our package.json +// import 'lodash.set'; // eslint-disable-line no-restricted-imports +// import 'lodash.setWith'; // eslint-disable-line no-restricted-imports +// import 'lodash.template'; // eslint-disable-line no-restricted-imports + +import 'lodash/set'; // eslint-disable-line no-restricted-imports +import 'lodash/setWith'; // eslint-disable-line no-restricted-imports +import 'lodash/template'; // eslint-disable-line no-restricted-imports + +import { set as f } from 'lodash/fp'; // eslint-disable-line no-restricted-imports +import { setWith as g } from 'lodash/fp'; // eslint-disable-line no-restricted-imports +import { assoc as h } from 'lodash/fp'; // eslint-disable-line no-restricted-imports +import { assocPath as i } from 'lodash/fp'; // eslint-disable-line no-restricted-imports +import { template as j } from 'lodash/fp'; // eslint-disable-line no-restricted-imports + +import 'lodash/fp/set'; // eslint-disable-line no-restricted-imports +import 'lodash/fp/setWith'; // eslint-disable-line no-restricted-imports +import 'lodash/fp/assoc'; // eslint-disable-line no-restricted-imports +import 'lodash/fp/assocPath'; // eslint-disable-line no-restricted-imports +import 'lodash/fp/template'; // eslint-disable-line no-restricted-imports + +// The following require statements can't be tested because they are not in our package.json +// require('lodash.set'); // eslint-disable-line no-restricted-modules +// require('lodash.setWith'); // eslint-disable-line no-restricted-modules +// require('lodash.template'); // eslint-disable-line no-restricted-modules + +require('lodash/set'); // eslint-disable-line no-restricted-modules +require('lodash/setWith'); // eslint-disable-line no-restricted-modules +require('lodash/template'); // eslint-disable-line no-restricted-modules + +require('lodash/fp/set'); // eslint-disable-line no-restricted-modules +require('lodash/fp/setWith'); // eslint-disable-line no-restricted-modules +require('lodash/fp/assoc'); // eslint-disable-line no-restricted-modules +require('lodash/fp/assocPath'); // eslint-disable-line no-restricted-modules +require('lodash/fp/template'); // eslint-disable-line no-restricted-modules + +const lodash = { + set() {}, + setWith() {}, + assoc() {}, + assocPath() {}, + template() {}, +}; +lodash.set(); // eslint-disable-line no-restricted-properties +lodash.setWith(); // eslint-disable-line no-restricted-properties +lodash.assoc(); // eslint-disable-line no-restricted-properties +lodash.assocPath(); // eslint-disable-line no-restricted-properties +lodash.template(); // eslint-disable-line no-restricted-properties + +const _ = lodash; +_.set(); // eslint-disable-line no-restricted-properties +_.setWith(); // eslint-disable-line no-restricted-properties +_.assoc(); // eslint-disable-line no-restricted-properties +_.assocPath(); // eslint-disable-line no-restricted-properties +_.template(); // eslint-disable-line no-restricted-properties + +// hack to ensure all imported variables are used +module.exports = [a, b, c, d, e, f, g, h, i, j]; diff --git a/src/plugins/console/server/services/spec_definitions_service.ts b/src/plugins/console/server/services/spec_definitions_service.ts index b5515ed1308fa..b978c3c326159 100644 --- a/src/plugins/console/server/services/spec_definitions_service.ts +++ b/src/plugins/console/server/services/spec_definitions_service.ts @@ -9,6 +9,7 @@ import _, { merge } from 'lodash'; import globby from 'globby'; import { basename, join, resolve } from 'path'; +import normalizePath from 'normalize-path'; import { readFileSync } from 'fs'; import { jsSpecLoaders } from '../lib'; @@ -115,8 +116,9 @@ export class SpecDefinitionsService { } private loadJSONSpecInDir(dirname: string) { - const generatedFiles = globby.sync(join(dirname, 'generated', '*.json')); - const overrideFiles = globby.sync(join(dirname, 'overrides', '*.json')); + // we need to normalize paths otherwise they don't work on windows, see https://github.com/elastic/kibana/issues/151032 + const generatedFiles = globby.sync(normalizePath(join(dirname, 'generated', '*.json'))); + const overrideFiles = globby.sync(normalizePath(join(dirname, 'overrides', '*.json'))); return generatedFiles.reduce((acc, file) => { const overrideFile = overrideFiles.find((f) => basename(f) === basename(file)); diff --git a/src/plugins/controls/public/control_group/editor/control_editor.tsx b/src/plugins/controls/public/control_group/editor/control_editor.tsx index 129d800e7b71a..61f0c574d3f01 100644 --- a/src/plugins/controls/public/control_group/editor/control_editor.tsx +++ b/src/plugins/controls/public/control_group/editor/control_editor.tsx @@ -109,7 +109,7 @@ export const ControlEditor = ({ }); const [defaultTitle, setDefaultTitle] = useState(); - const [currentTitle, setCurrentTitle] = useState(title); + const [currentTitle, setCurrentTitle] = useState(title ?? ''); const [currentWidth, setCurrentWidth] = useState(width); const [currentGrow, setCurrentGrow] = useState(grow); const [controlEditorValid, setControlEditorValid] = useState(false); @@ -198,27 +198,27 @@ export const ControlEditor = ({ /> )} - - { - return Boolean(fieldRegistry?.[field.name]); - }} - selectedFieldName={selectedField} - dataView={dataView} - onSelectField={(field) => { - onTypeEditorChange({ - fieldName: field.name, - }); - const newDefaultTitle = field.displayName ?? field.name; - setDefaultTitle(newDefaultTitle); - setSelectedField(field.name); - if (!currentTitle || currentTitle === defaultTitle) { - setCurrentTitle(newDefaultTitle); - updateTitle(newDefaultTitle); - } - }} - /> - + {fieldRegistry && ( + + Boolean(fieldRegistry[field.name])} + selectedFieldName={selectedField} + dataView={dataView} + onSelectField={(field) => { + onTypeEditorChange({ + fieldName: field.name, + }); + const newDefaultTitle = field.displayName ?? field.name; + setDefaultTitle(newDefaultTitle); + setSelectedField(field.name); + if (!currentTitle || currentTitle === defaultTitle) { + setCurrentTitle(newDefaultTitle); + updateTitle(newDefaultTitle); + } + }} + /> + + )} {factory ? ( diff --git a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts index f7d710aaa0f95..4144d9cd5b3af 100644 --- a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts +++ b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts @@ -68,6 +68,11 @@ export const getCreateVisualizationButtonTitle = () => defaultMessage: 'Create visualization', }); +export const getQuickCreateButtonGroupLegend = () => + i18n.translate('dashboard.solutionToolbar.quickCreateButtonGroupLegend', { + defaultMessage: 'Shortcuts to popular visualization types', + }); + export const getNewDashboardTitle = () => i18n.translate('dashboard.savedDashboard.newDashboardTitle', { defaultMessage: 'New Dashboard', diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/controls_toolbar_button/controls_toolbar_button.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/controls_toolbar_button/controls_toolbar_button.tsx index 837fa7c28f313..116f735fb6aac 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/controls_toolbar_button/controls_toolbar_button.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/controls_toolbar_button/controls_toolbar_button.tsx @@ -7,20 +7,20 @@ */ import React from 'react'; + import { EuiContextMenuPanel } from '@elastic/eui'; -import { SolutionToolbarPopover } from '@kbn/presentation-util-plugin/public'; +import { ToolbarPopover } from '@kbn/shared-ux-button-toolbar'; import type { ControlGroupContainer } from '@kbn/controls-plugin/public'; + import { getControlButtonTitle } from '../../_dashboard_app_strings'; import { AddDataControlButton } from './add_data_control_button'; import { AddTimeSliderControlButton } from './add_time_slider_control_button'; export function ControlsToolbarButton({ controlGroup }: { controlGroup: ControlGroupContainer }) { return ( - @@ -33,6 +33,6 @@ export function ControlsToolbarButton({ controlGroup }: { controlGroup: ControlG ]} /> )} - + ); } diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx index b22eddc8e1dc6..f3b67afbac91d 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx @@ -8,23 +8,21 @@ import { METRIC_TYPE } from '@kbn/analytics'; import { EmbeddableFactory } from '@kbn/embeddable-plugin/public'; -import { - AddFromLibraryButton, - PrimaryActionButton, - QuickButtonGroup, - QuickButtonProps, - SolutionToolbar, -} from '@kbn/presentation-util-plugin/public'; +import { AddFromLibraryButton, Toolbar, ToolbarButton } from '@kbn/shared-ux-button-toolbar'; +import { IconButton, IconButtonGroup } from '@kbn/shared-ux-button-toolbar'; import { BaseVisType, VisTypeAlias } from '@kbn/visualizations-plugin/public'; import React from 'react'; import { useCallback } from 'react'; -import { useEuiTheme } from '@elastic/eui'; +import { IconType, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { dashboardReplacePanelActionStrings } from '../../dashboard_actions/_dashboard_actions_strings'; import { DASHBOARD_APP_ID, DASHBOARD_UI_METRIC_ID } from '../../dashboard_constants'; import { useDashboardContainerContext } from '../../dashboard_container/dashboard_container_context'; import { pluginServices } from '../../services/plugin_services'; -import { getCreateVisualizationButtonTitle } from '../_dashboard_app_strings'; +import { + getCreateVisualizationButtonTitle, + getQuickCreateButtonGroupLegend, +} from '../_dashboard_app_strings'; import { EditorMenu } from './editor_menu'; import { ControlsToolbarButton } from './controls_toolbar_button'; @@ -33,7 +31,6 @@ export function DashboardEditingToolbar() { usageCollection, data: { search }, notifications: { toasts }, - settings: { uiSettings }, embeddable: { getStateTransfer, getEmbeddableFactory }, visualizations: { get: getVisualization, getAliases: getVisTypeAliases }, } = pluginServices.getServices(); @@ -42,7 +39,6 @@ export function DashboardEditingToolbar() { const { embeddableInstance: dashboardContainer } = useDashboardContainerContext(); const stateTransferService = getStateTransfer(); - const IS_DARK_THEME = uiSettings.get('theme:darkMode'); const lensAlias = getVisTypeAliases().find(({ name }) => name === 'lens'); const quickButtonVisTypes: Array< @@ -120,7 +116,9 @@ export function DashboardEditingToolbar() { [trackUiMetric, dashboardContainer, toasts] ); - const getVisTypeQuickButton = (quickButtonForType: typeof quickButtonVisTypes[0]) => { + const getVisTypeQuickButton = ( + quickButtonForType: typeof quickButtonVisTypes[0] + ): IconButton | undefined => { if (quickButtonForType.type === 'vis') { const visTypeName = quickButtonForType.visType; const visType = @@ -130,19 +128,17 @@ export function DashboardEditingToolbar() { if (visType) { if ('aliasPath' in visType) { const { name, icon, title } = visType as VisTypeAlias; - return { + label: title, iconType: icon, - createType: title, onClick: createNewVisType(visType as VisTypeAlias), 'data-test-subj': `dashboardQuickButton${name}`, }; } else { - const { name, icon, title, titleInWizard } = visType as BaseVisType; - + const { name, icon, title, titleInWizard } = visType as BaseVisType & { icon: IconType }; return { + label: titleInWizard || title, iconType: icon, - createType: titleInWizard || title, onClick: createNewVisType(visType as BaseVisType), 'data-test-subj': `dashboardQuickButton${name}`, }; @@ -151,22 +147,25 @@ export function DashboardEditingToolbar() { } else { const embeddableType = quickButtonForType.embeddableType; const embeddableFactory = getEmbeddableFactory(embeddableType); - return { - iconType: embeddableFactory?.getIconType(), - createType: embeddableFactory?.getDisplayName(), - onClick: () => { - if (embeddableFactory) { - createNewEmbeddable(embeddableFactory); - } - }, - 'data-test-subj': `dashboardQuickButton${embeddableType}`, - }; + if (embeddableFactory) { + return { + label: embeddableFactory.getDisplayName(), + iconType: embeddableFactory.getIconType(), + onClick: () => { + if (embeddableFactory) { + createNewEmbeddable(embeddableFactory); + } + }, + 'data-test-subj': `dashboardQuickButton${embeddableType}`, + }; + } } }; - const quickButtons = quickButtonVisTypes - .map(getVisTypeQuickButton) - .filter((button) => button) as QuickButtonProps[]; + const quickButtons: IconButton[] = quickButtonVisTypes.reduce((accumulator, type) => { + const button = getVisTypeQuickButton(type); + return button ? [...accumulator, button] : accumulator; + }, [] as IconButton[]); const extraButtons = [ , @@ -185,21 +184,23 @@ export function DashboardEditingToolbar() { padding: 0 ${euiTheme.size.s} ${euiTheme.size.s} ${euiTheme.size.s}; `} > - + {{ - primaryActionButton: ( - ), - quickButtonGroup: , + iconButtonGroup: ( + + ), extraButtons, }} - +
); } diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/editor_menu.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/editor_menu.tsx index 5de32e3b10019..46ab6214e7ffd 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/editor_menu.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/editor_menu.tsx @@ -16,8 +16,8 @@ import { EuiFlexItem, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { ToolbarPopover } from '@kbn/shared-ux-button-toolbar'; import { type BaseVisType, VisGroups, type VisTypeAlias } from '@kbn/visualizations-plugin/public'; -import { SolutionToolbarPopover } from '@kbn/presentation-util-plugin/public'; import type { EmbeddableFactory } from '@kbn/embeddable-plugin/public'; import { pluginServices } from '../../services/plugin_services'; import { DASHBOARD_APP_ID } from '../../dashboard_constants'; @@ -261,13 +261,11 @@ export const EditorMenu = ({ createNewVisType, createNewEmbeddable }: Props) => ]; }; return ( - @@ -279,6 +277,6 @@ export const EditorMenu = ({ createNewVisType, createNewEmbeddable }: Props) => data-test-subj="dashboardEditorContextMenu" /> )} - + ); }; diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json index ddf6e65028ea2..17ec86d25e6ef 100644 --- a/src/plugins/dashboard/tsconfig.json +++ b/src/plugins/dashboard/tsconfig.json @@ -53,6 +53,7 @@ "@kbn/core-execution-context-common", "@kbn/core-custom-branding-browser", "@kbn/shared-ux-router", + "@kbn/shared-ux-button-toolbar", ], "exclude": [ "target/**/*", diff --git a/src/plugins/data/server/search/saved_objects/search_session.ts b/src/plugins/data/server/search/saved_objects/search_session.ts index 5e3906cfd8f63..ef0f960c84e8c 100644 --- a/src/plugins/data/server/search/saved_objects/search_session.ts +++ b/src/plugins/data/server/search/saved_objects/search_session.ts @@ -64,4 +64,14 @@ export const searchSessionSavedObjectType: SavedObjectsType = { }, }, migrations: searchSessionSavedObjectMigrations, + excludeOnUpgrade: async () => { + return { + bool: { + must: [ + { term: { type: SEARCH_SESSION_TYPE } }, + { match: { 'search-session.persisted': false } }, + ], + }, + }; + }, }; diff --git a/src/plugins/data_view_editor/public/data_view_editor_service.ts b/src/plugins/data_view_editor/public/data_view_editor_service.ts index 4bfd04c912a6c..798e339b7ee3f 100644 --- a/src/plugins/data_view_editor/public/data_view_editor_service.ts +++ b/src/plugins/data_view_editor/public/data_view_editor_service.ts @@ -129,8 +129,6 @@ export class DataViewEditorService { private requireTimestampField: boolean; private type = INDEX_PATTERN_TYPE.DEFAULT; - // state - private state = { ...defaultDataViewEditorState }; private indexPattern = ''; private allowHidden = false; @@ -165,8 +163,7 @@ export class DataViewEditorService { private currentLoadingMatchedIndices = 0; private updateState = (newState: Partial) => { - this.state = { ...this.state, ...newState }; - this.state$.next(this.state); + this.state$.next({ ...this.state$.getValue(), ...newState }); }; private getRollupIndexCaps = async () => { @@ -324,7 +321,8 @@ export class DataViewEditorService { }; private loadTimestampFields = async () => { - if (this.state.matchedIndices.exactMatchedIndices.length === 0) { + const currentState = this.state$.getValue(); + if (currentState.matchedIndices.exactMatchedIndices.length === 0) { this.updateState({ timestampFieldOptions: [], loadingTimestampFields: false }); return; } @@ -335,7 +333,7 @@ export class DataViewEditorService { }; if (this.type === INDEX_PATTERN_TYPE.ROLLUP) { getFieldsOptions.type = INDEX_PATTERN_TYPE.ROLLUP; - getFieldsOptions.rollupIndex = this.state.rollupIndexName || ''; + getFieldsOptions.rollupIndex = currentState.rollupIndexName || ''; } let timestampFieldOptions: TimestampOption[] = []; diff --git a/src/plugins/data_view_field_editor/public/components/preview/preview_controller.ts b/src/plugins/data_view_field_editor/public/components/preview/preview_controller.ts index b94051bb0107d..80b11e74597aa 100644 --- a/src/plugins/data_view_field_editor/public/components/preview/preview_controller.ts +++ b/src/plugins/data_view_field_editor/public/components/preview/preview_controller.ts @@ -48,24 +48,18 @@ export class PreviewController { private dataView: DataView; // @ts-ignore private search: ISearchStart; - private state: PreviewState = previewStateDefault; private internalState$: BehaviorSubject; state$: BehaviorObservable; private updateState = (newState: Partial) => { - this.state = { ...this.state, ...newState }; - this.publishState(); - }; - - private publishState = () => { - // todo try removing object copy - this.internalState$.next({ ...this.state }); + this.internalState$.next({ ...this.state$.getValue(), ...newState }); }; togglePinnedField = (fieldName: string) => { + const currentState = this.state$.getValue(); const pinnedFields = { - ...this.state.pinnedFields, - [fieldName]: !this.state.pinnedFields[fieldName], + ...currentState.pinnedFields, + [fieldName]: !currentState.pinnedFields[fieldName], }; this.updateState({ pinnedFields }); @@ -84,18 +78,20 @@ export class PreviewController { }; goToNextDocument = () => { - if (this.state.currentIdx >= this.state.documents.length - 1) { + const currentState = this.state$.getValue(); + if (currentState.currentIdx >= currentState.documents.length - 1) { this.updateState({ currentIdx: 0 }); } else { - this.updateState({ currentIdx: this.state.currentIdx + 1 }); + this.updateState({ currentIdx: currentState.currentIdx + 1 }); } }; goToPreviousDocument = () => { - if (this.state.currentIdx === 0) { - this.updateState({ currentIdx: this.state.documents.length - 1 }); + const currentState = this.state$.getValue(); + if (currentState.currentIdx === 0) { + this.updateState({ currentIdx: currentState.documents.length - 1 }); } else { - this.updateState({ currentIdx: this.state.currentIdx - 1 }); + this.updateState({ currentIdx: currentState.currentIdx - 1 }); } }; diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index 65d23292486f3..13fbb9cec243e 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -583,7 +583,7 @@ export class DataViewsService { } catch (err) { if (err instanceof DataViewMissingIndices) { this.onNotification( - { title: err.message, color: 'danger', iconType: 'alert' }, + { title: err.message, color: 'danger', iconType: 'error' }, `refreshFields:${dataView.getIndexPattern()}` ); } @@ -637,7 +637,7 @@ export class DataViewsService { if (err instanceof DataViewMissingIndices) { if (displayErrors) { this.onNotification( - { title: err.message, color: 'danger', iconType: 'alert' }, + { title: err.message, color: 'danger', iconType: 'error' }, `refreshFieldSpecMap:${title}` ); } @@ -807,7 +807,7 @@ export class DataViewsService { { title: err.message, color: 'danger', - iconType: 'alert', + iconType: 'error', }, `initFromSavedObject:${spec.title}` ); diff --git a/src/plugins/discover/public/__mocks__/__storybook_mocks__/get_data_view_mock.tsx b/src/plugins/discover/public/__mocks__/__storybook_mocks__/get_data_view_mock.tsx index 718f43892aac2..ee6736519ca31 100644 --- a/src/plugins/discover/public/__mocks__/__storybook_mocks__/get_data_view_mock.tsx +++ b/src/plugins/discover/public/__mocks__/__storybook_mocks__/get_data_view_mock.tsx @@ -10,13 +10,6 @@ import { DataView } from '@kbn/data-views-plugin/common'; export function getDataViewMock(isTimebased = true) { const fields = [ - { - name: '_index', - type: 'string', - scripted: false, - filterable: true, - aggregatable: false, - }, { name: 'date', type: 'date', @@ -80,14 +73,16 @@ export function getDataViewMock(isTimebased = true) { getFormatterForField: () => ({ convert: (name: string) => name, }), - getFieldByName: () => { - return fields[0]; + getFieldByName: (name: string) => { + return fields.find((field) => field.name === name); }, + getIndexPattern: () => 'test', metaFields: [], timeFieldName: isTimebased ? 'date' : undefined, + isPersisted: () => true, } as unknown as DataView; - dataViewMock.fields.getByName = () => fields[0]; + dataViewMock.fields.getByName = (name: string) => fields.find((field) => field.name === name); dataViewMock.fields.getAll = () => fields; return dataViewMock; } diff --git a/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx b/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx index d8309e452f7a1..975317e918cb3 100644 --- a/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx +++ b/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx @@ -29,6 +29,7 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { Plugin as NavigationPublicPlugin } from '@kbn/navigation-plugin/public'; import { SearchBar, UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { SavedQuery } from '@kbn/data-plugin/public'; +import { BehaviorSubject, Observable } from 'rxjs'; const NavigationPlugin = new NavigationPublicPlugin({} as PluginInitializerContext); @@ -57,8 +58,18 @@ export const uiSettingsMock = { }, } as unknown as IUiSettingsClient; -const services = { - core: { http: { basePath: { prepend: () => void 0 } } }, +const filterManager = { + getGlobalFilters: () => [], + getAppFilters: () => [], + getFetches$: () => new Observable(), +}; + +export const services = { + core: { + http: { basePath: { prepend: () => void 0 } }, + notifications: { toasts: {} }, + docLinks: { links: { discover: {} } }, + }, storage: new LocalStorageMock({ [SIDEBAR_CLOSED_KEY]: false, }) as unknown as Storage, @@ -74,12 +85,53 @@ const services = { from: 'now-7d', to: 'now', }), + getRefreshInterval: () => ({}), + getFetch$: () => new Observable(), + getAutoRefreshFetch$: () => new Observable(), + calculateBounds: () => ({ min: undefined, max: undefined }), + getTimeDefaults: () => ({}), + createFilter: () => ({}), }, }, savedQueries: { findSavedQueries: () => Promise.resolve({ queries: [] as SavedQuery[] }) }, + queryString: { + getDefaultQuery: () => { + return { query: '', language: 'kuery' }; + }, + getUpdates$: () => new Observable(), + }, + filterManager, + getState: () => { + return { + filters: [], + query: { query: '', language: 'kuery' }, + }; + }, + state$: new Observable(), + }, + search: { + session: { + getSession$: () => { + return new BehaviorSubject('test').asObservable(); + }, + state$: new Observable(), + }, + searchSource: { + createEmpty: () => { + const empty = { + setField: () => { + return empty; + }, + fetch$: () => new Observable(), + }; + return empty; + }, + }, }, dataViews: { getIdsWithTitle: () => Promise.resolve([]), + get: () => Promise.resolve({}), + find: () => Promise.resolve([]), }, }, uiSettings: uiSettingsMock, @@ -120,10 +172,7 @@ const services = { }, docLinks: { links: { discover: {} } }, addBasePath: (path: string) => path, - filterManager: { - getGlobalFilters: () => [], - getAppFilters: () => [], - }, + filterManager, history: () => ({}), fieldFormats: { deserialize: () => { @@ -134,6 +183,15 @@ const services = { toastNotifications: { addInfo: action('add toast'), }, + lens: { + EmbeddableComponent:
Histogram
, + }, + unifiedSearch: { + autocomplete: { + hasQuerySuggestions: () => Promise.resolve([]), + getQuerySuggestions: () => Promise.resolve([]), + }, + }, } as unknown as DiscoverServices; export const withDiscoverServices = (Component: FunctionComponent) => { diff --git a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx index b01a05f932e13..0bb6947dc7674 100644 --- a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx +++ b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx @@ -138,7 +138,7 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { const availableFields$ = stateContainer?.dataState.data$.availableFields$; const sub = embeddable?.getOutput$().subscribe((output: DataVisualizerGridEmbeddableOutput) => { if (output.showDistributions !== undefined && stateContainer) { - stateContainer.setAppState({ hideAggregatedPreview: !output.showDistributions }); + stateContainer.appState.update({ hideAggregatedPreview: !output.showDistributions }); } }); diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx b/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx index 8392bb7c0ed49..d661a85289a76 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx @@ -9,6 +9,7 @@ import React, { useState } from 'react'; import { storiesOf } from '@storybook/react'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { DiscoverMainProvider } from '../../../services/discover_state_provider'; import { AppState } from '../../../services/discover_app_state_container'; import { getDataViewMock } from '../../../../../__mocks__/__storybook_mocks__/get_data_view_mock'; import { withDiscoverServices } from '../../../../../__mocks__/__storybook_mocks__/with_discover_services'; @@ -22,7 +23,7 @@ setHeaderActionMenuMounter(() => void 0); const DiscoverLayoutStory = (layoutProps: DiscoverLayoutProps) => { const [state, setState] = useState({}); - const setAppState = (newState: Partial) => { + const update = (newState: Partial) => { setState((prevState) => ({ ...prevState, ...newState })); }; @@ -33,8 +34,7 @@ const DiscoverLayoutStory = (layoutProps: DiscoverLayoutProps) => { {...layoutProps} stateContainer={{ ...layoutProps.stateContainer, - appState: { ...layoutProps.stateContainer.appState, getState }, - setAppState, + appState: { ...layoutProps.stateContainer.appState, getState, update }, }} /> ); @@ -42,27 +42,42 @@ const DiscoverLayoutStory = (layoutProps: DiscoverLayoutProps) => { storiesOf('components/layout/DiscoverLayout', module).add( 'Data view with timestamp', - withDiscoverServices(() => ( - - - - )) + withDiscoverServices(() => { + const props = getDocumentsLayoutProps(getDataViewMock(true)); + return ( + + + + + + ); + }) ); storiesOf('components/layout/DiscoverLayout', module).add( 'Data view without timestamp', - withDiscoverServices(() => ( - - - - )) + withDiscoverServices(() => { + const props = getDocumentsLayoutProps(getDataViewMock(false)); + return ( + + + + + + ); + }) ); storiesOf('components/layout/DiscoverLayout', module).add( 'SQL view', - withDiscoverServices(() => ( - - - - )) + withDiscoverServices(() => { + const props = getPlainRecordLayoutProps(getDataViewMock(false)); + return ( + + + + + + ); + }) ); diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts index 3d7e72b32bb12..1082a5b127397 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts @@ -6,11 +6,12 @@ * Side Public License, v 1. */ -import { DataView, DataViewAttributes, SavedObject } from '@kbn/data-views-plugin/common'; +import { DataView } from '@kbn/data-views-plugin/common'; import { SearchSource } from '@kbn/data-plugin/common'; -import { BehaviorSubject, Subject } from 'rxjs'; +import { BehaviorSubject, Observable, Subject } from 'rxjs'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { action } from '@storybook/addon-actions'; +import { createHashHistory } from 'history'; import { FetchStatus } from '../../../../types'; import { AvailableFields$, @@ -23,7 +24,11 @@ import { buildDataTableRecordList } from '../../../../../utils/build_data_record import { esHits } from '../../../../../__mocks__/es_hits'; import { SavedSearch } from '../../../../..'; import { DiscoverLayoutProps } from '../types'; -import { DiscoverStateContainer } from '../../../services/discover_state'; +import { + DiscoverStateContainer, + getDiscoverStateContainer, +} from '../../../services/discover_state'; +import { services } from '../../../../../__mocks__/__storybook_mocks__/with_discover_services'; const documentObservables = { main$: new BehaviorSubject({ @@ -45,6 +50,7 @@ const documentObservables = { fetchStatus: FetchStatus.COMPLETE, result: Number(esHits.length), }) as DataTotalHits$, + fetch$: new Observable(), }; const plainRecordObservables = { @@ -72,17 +78,11 @@ const plainRecordObservables = { }) as DataTotalHits$, }; -const getCommonProps = (dataView: DataView) => { +const getCommonProps = () => { const searchSourceMock = {} as unknown as SearchSource; - const dataViewList = [dataView].map((ip) => { - return { ...ip, ...{ attributes: { title: ip.getIndexPattern() } } }; - }) as unknown as Array>; - const savedSearchMock = {} as unknown as SavedSearch; return { - dataView, - dataViewList, inspectorAdapters: { requests: new RequestAdapter() }, navigateTo: action('navigate to somewhere nice'), onChangeDataView: action('change the data view'), @@ -104,33 +104,70 @@ const getCommonProps = (dataView: DataView) => { }; }; -export function getDocumentsLayoutProps(dataView: DataView) { +function getSavedSearch(dataView: DataView) { return { - ...getCommonProps(dataView), - savedSearchData$: documentObservables, - state: { - columns: ['name', 'message', 'bytes'], - sort: [['date', 'desc']], - query: { - language: 'kuery', - query: '', + searchSource: { + getField: (value: string) => { + if (value === 'index') { + return dataView; + } + }, + getOwnField: () => { + return { + query: '', + }; + }, + createChild: () => { + return { + fetch$: () => new Observable(), + } as unknown as SearchSource; }, - filters: [], }, + } as unknown as SavedSearch; +} + +export function getDocumentsLayoutProps(dataView: DataView) { + const stateContainer = getDiscoverStateContainer({ + history: createHashHistory(), + savedSearch: getSavedSearch(dataView), + services, + }); + stateContainer.appState.set({ + columns: ['name', 'message', 'bytes'], + sort: dataView.timeFieldName ? [['date', 'desc']] : [['name', 'desc']], + query: { + language: 'kuery', + query: '', + }, + filters: [], + hideChart: true, + }); + stateContainer.actions.setDataView(dataView); + stateContainer.dataState.data$ = documentObservables; + return { + ...getCommonProps(), + stateContainer, } as unknown as DiscoverLayoutProps; } export const getPlainRecordLayoutProps = (dataView: DataView) => { - return { - ...getCommonProps(dataView), - savedSearchData$: plainRecordObservables, - state: { - columns: ['name', 'message', 'bytes'], - sort: [['date', 'desc']], - query: { - sql: 'SELECT * FROM "kibana_sample_data_ecommerce"', - }, - filters: [], + const stateContainer = getDiscoverStateContainer({ + history: createHashHistory(), + savedSearch: getSavedSearch(dataView), + services, + }); + stateContainer.appState.set({ + columns: ['name', 'message', 'bytes'], + sort: [['date', 'desc']], + query: { + sql: 'SELECT * FROM "kibana_sample_data_ecommerce"', }, + filters: [], + }); + stateContainer.actions.setDataView(dataView); + stateContainer.dataState.data$ = plainRecordObservables; + return { + ...getCommonProps(), + stateContainer, } as unknown as DiscoverLayoutProps; }; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx index d73c1163c8a0f..ab45bb1ce606d 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx @@ -12,7 +12,6 @@ import { mountWithIntl } from '@kbn/test-jest-helpers'; import { setHeaderActionMenuMounter } from '../../../../kibana_services'; import { esHits } from '../../../../__mocks__/es_hits'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; -import { DiscoverStateContainer } from '../../services/discover_state'; import { DataDocuments$ } from '../../services/discover_data_state_container'; import { discoverServiceMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; @@ -38,7 +37,7 @@ function mountComponent(fetchStatus: FetchStatus, hits: EsHitRecord[]) { result: hits.map((hit) => buildDataTableRecord(hit, dataViewMock)), }) as DataDocuments$; const stateContainer = getDiscoverStateMock({}); - stateContainer.setAppState({ index: dataViewMock.id }); + stateContainer.appState.update({ index: dataViewMock.id }); stateContainer.dataState.data$.documents$ = documents$; const props = { @@ -83,26 +82,20 @@ describe('Discover documents layout', () => { }); test('should set rounded width to state on resize column', () => { - let state = { + const state = { grid: { columns: { timestamp: { width: 173 }, someField: { width: 197 } } }, } as AppState; - const stateContainer = { - setAppState: (newState: Partial) => { - state = { ...state, ...newState }; - }, - appState: { - getState: () => state, - }, - } as unknown as DiscoverStateContainer; + const container = getDiscoverStateMock({}); + container.appState.update(state); onResize( { columnId: 'someField', width: 205.5435345534, }, - stateContainer + container ); - expect(state.grid?.columns?.someField.width).toEqual(206); + expect(container.appState.getState().grid?.columns?.someField.width).toEqual(206); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index 647a6561b7cf0..2a9698050eade 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -55,7 +55,7 @@ export const onResize = ( width: Math.round(colSettings.width), }; const newGrid = { ...grid, columns: newColumns }; - stateContainer.setAppState({ grid: newGrid }); + stateContainer.appState.update({ grid: newGrid }); }; function DiscoverDocumentsComponent({ @@ -123,7 +123,7 @@ function DiscoverDocumentsComponent({ config: uiSettings, dataView, dataViews, - setAppState: stateContainer.setAppState, + setAppState: stateContainer.appState.update, useNewFieldsApi, columns, sort, @@ -136,21 +136,21 @@ function DiscoverDocumentsComponent({ const onUpdateRowsPerPage = useCallback( (nextRowsPerPage: number) => { - stateContainer.setAppState({ rowsPerPage: nextRowsPerPage }); + stateContainer.appState.update({ rowsPerPage: nextRowsPerPage }); }, [stateContainer] ); const onSort = useCallback( (nextSort: string[][]) => { - stateContainer.setAppState({ sort: nextSort }); + stateContainer.appState.update({ sort: nextSort }); }, [stateContainer] ); const onUpdateRowHeight = useCallback( (newRowHeight: number) => { - stateContainer.setAppState({ rowHeight: newRowHeight }); + stateContainer.appState.update({ rowHeight: newRowHeight }); }, [stateContainer] ); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx index 2396325ac82cc..cc975e9008686 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx @@ -39,13 +39,11 @@ import { act } from 'react-dom/test-utils'; function getStateContainer() { const stateContainer = getDiscoverStateMock({ isTimeBased: true }); - stateContainer.setAppState({ + stateContainer.appState.update({ interval: 'auto', hideChart: false, }); - stateContainer.setAppState = jest.fn(); - return stateContainer; } @@ -130,9 +128,9 @@ const mountComponent = async ({ onAddFilter: jest.fn(), resetSavedSearch, resizeRef: { current: null }, - searchSessionManager: createSearchSessionMock(session).searchSessionManager, inspectorAdapters: { requests: new RequestAdapter() }, }; + stateContainer.searchSessionManager = createSearchSessionMock(session).searchSessionManager; const coreTheme$ = new BehaviorSubject({ darkMode: false }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx index 68a5d8e1c7ee9..5a74e58184ff0 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx @@ -11,7 +11,6 @@ import { UnifiedHistogramContainer } from '@kbn/unified-histogram-plugin/public' import { css } from '@emotion/react'; import useObservable from 'react-use/lib/useObservable'; import { useDiscoverHistogram } from './use_discover_histogram'; -import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; import type { InspectorAdapters } from '../../hooks/use_inspector'; import { type DiscoverMainContentProps, DiscoverMainContent } from './discover_main_content'; import { ResetSearchButton } from './reset_search_button'; @@ -20,7 +19,6 @@ export interface DiscoverHistogramLayoutProps extends DiscoverMainContentProps { resetSavedSearch: () => void; resizeRef: RefObject; inspectorAdapters: InspectorAdapters; - searchSessionManager: DiscoverSearchSessionManager; } const histogramLayoutCss = css` @@ -35,7 +33,6 @@ export const DiscoverHistogramLayout = ({ stateContainer, resizeRef, inspectorAdapters, - searchSessionManager, ...mainContentProps }: DiscoverHistogramLayoutProps) => { const commonProps = { @@ -43,8 +40,7 @@ export const DiscoverHistogramLayout = ({ stateContainer, savedSearchData$: stateContainer.dataState.data$, }; - - const searchSessionId = useObservable(searchSessionManager.searchSessionId$); + const searchSessionId = useObservable(stateContainer.searchSessionManager.searchSessionId$); const { hideChart, setUnifiedHistogramApi } = useDiscoverHistogram({ inspectorAdapters, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index f14d89ead5b81..ec9360b3bb1f0 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -107,7 +107,7 @@ async function mountComponent( session.getSession$.mockReturnValue(new BehaviorSubject('123')); - stateContainer.setAppState({ interval: 'auto', query }); + stateContainer.appState.update({ interval: 'auto', query }); stateContainer.internalState.transitions.setDataView(dataView); const props = { @@ -124,9 +124,9 @@ async function mountComponent( setExpandedDoc: jest.fn(), persistDataView: jest.fn(), updateAdHocDataViewId: jest.fn(), - searchSessionManager: createSearchSessionMock(session).searchSessionManager, updateDataViewList: jest.fn(), }; + stateContainer.searchSessionManager = createSearchSessionMock(session).searchSessionManager; const component = mountWithIntl( diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index da47f1c1e9626..3e7bb1bc891b7 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -66,7 +66,6 @@ export function DiscoverLayout({ stateContainer, persistDataView, updateAdHocDataViewId, - searchSessionManager, updateDataViewList, }: DiscoverLayoutProps) { const { @@ -137,7 +136,7 @@ export function DiscoverLayout({ config: uiSettings, dataView, dataViews, - setAppState: stateContainer.setAppState, + setAppState: stateContainer.appState.update, useNewFieldsApi, columns, sort, @@ -251,7 +250,6 @@ export function DiscoverLayout({ onFieldEdited={onFieldEdited} resizeRef={resizeRef} inspectorAdapters={inspectorAdapters} - searchSessionManager={searchSessionManager} /> {resultState === 'loading' && } @@ -272,12 +270,10 @@ export function DiscoverLayout({ resetSavedSearch, resultState, savedSearch, - searchSessionManager, setExpandedDoc, stateContainer, viewMode, ]); - return (

{ - stateContainer.setAppState({ viewMode: mode }); + stateContainer.appState.update({ viewMode: mode }); if (trackUiMetric) { if (mode === VIEW_MODE.AGGREGATED_LEVEL) { diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index 0d9b0c37e3009..d84b6807c080e 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -12,7 +12,6 @@ import type { ISearchSource } from '@kbn/data-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; import { DiscoverStateContainer } from '../../services/discover_state'; -import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; import type { InspectorAdapters } from '../../hooks/use_inspector'; export interface DiscoverLayoutProps { @@ -31,6 +30,5 @@ export interface DiscoverLayoutProps { stateContainer: DiscoverStateContainer; persistDataView: (dataView: DataView) => Promise; updateAdHocDataViewId: (dataView: DataView) => Promise; - searchSessionManager: DiscoverSearchSessionManager; updateDataViewList: (newAdHocDataViews: DataView[]) => void; } diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx index 8463b380efc8f..e69da4b4178d4 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx @@ -86,14 +86,16 @@ const mockCheckHitCount = checkHitCount as jest.MockedFunction { const getStateContainer = () => { const stateContainer = getDiscoverStateMock({ isTimeBased: true }); - stateContainer.setAppState({ + stateContainer.appState.update({ interval: 'auto', hideChart: false, breakdownField: 'extension', }); - const wrappedStateContainer = Object.create(stateContainer); - wrappedStateContainer.setAppState = jest.fn((newState) => stateContainer.setAppState(newState)); - return wrappedStateContainer; + const appState = stateContainer.appState; + const wrappedStateContainer = Object.create(appState); + wrappedStateContainer.update = jest.fn((newState) => appState.update(newState)); + stateContainer.appState = wrappedStateContainer; + return stateContainer; }; const renderUseDiscoverHistogram = async ({ @@ -222,7 +224,7 @@ describe('useDiscoverHistogram', () => { hook.result.current.setUnifiedHistogramApi(api); }); expect(inspectorAdapters.lensRequests).toBe(lensRequestAdapter); - expect(stateContainer.setAppState).toHaveBeenCalledWith({ + expect(stateContainer.appState.update).toHaveBeenCalledWith({ interval: state.timeInterval, hideChart: state.chartHidden, breakdownField: state.breakdownField, @@ -245,7 +247,7 @@ describe('useDiscoverHistogram', () => { act(() => { hook.result.current.setUnifiedHistogramApi(api); }); - expect(stateContainer.setAppState).not.toHaveBeenCalled(); + expect(stateContainer.appState.update).not.toHaveBeenCalled(); }); it('should sync the state container state with Unified Histogram', async () => { @@ -446,10 +448,10 @@ describe('useDiscoverHistogram', () => { hook.result.current.setUnifiedHistogramApi(api); }); act(() => { - stateContainer.setAppState({ hideChart: true }); + stateContainer.appState.update({ hideChart: true }); }); act(() => { - stateContainer.setAppState({ hideChart: false }); + stateContainer.appState.update({ hideChart: false }); }); act(() => { savedSearchFetch$.next({ reset: false, searchSessionId: '1234' }); diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts index d259252f18686..a74f0d4358ea6 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -122,7 +122,7 @@ export const useDiscoverHistogram = ({ }; if (!isEqual(oldState, newState)) { - stateContainer.setAppState(newState); + stateContainer.appState.update(newState); } }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx index e31445344b82b..17945e7e3e027 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx @@ -8,8 +8,10 @@ import React from 'react'; import { findTestSubject } from '@elastic/eui/lib/test'; +import { ReactWrapper } from 'enzyme'; import { mountWithIntl } from '@kbn/test-jest-helpers'; - +import { EuiLoadingSpinner } from '@elastic/eui'; +import { act } from 'react-dom/test-utils'; import { DiscoverFieldDetails } from './discover_field_details'; import { DataViewField } from '@kbn/data-views-plugin/public'; import { stubDataView, stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; @@ -52,4 +54,57 @@ describe('discover sidebar field details', function () { onAddButton.simulate('click'); expect(onAddFilter).toHaveBeenCalledWith('_exists_', visualizableField.name, '+'); }); + + it('should stay in sync with documents$ state', async function () { + const testDocuments$ = new BehaviorSubject({ + fetchStatus: FetchStatus.LOADING, + }) as DataDocuments$; + const visualizableField = new DataViewField({ + name: 'bytes', + type: 'number', + esTypes: ['long'], + count: 10, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }); + let component: ReactWrapper; + + await act(async () => { + component = await mountWithIntl( + + ); + }); + + expect(component!.find(EuiLoadingSpinner).exists()).toBeTruthy(); + + await act(async () => { + testDocuments$.next({ + fetchStatus: FetchStatus.COMPLETE, + result: hits, + }); + }); + + await component!.update(); + + expect(component!.find(EuiLoadingSpinner).exists()).toBeFalsy(); + expect( + findTestSubject(component!, `discoverFieldDetails-${visualizableField.name}`).exists() + ).toBeTruthy(); + + await act(async () => { + testDocuments$.next({ + fetchStatus: FetchStatus.UNINITIALIZED, + }); + }); + + await component!.update(); + + expect(component!.isEmptyRender()).toBeTruthy(); + }); }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx index 0a3d1b5c58072..aa027376d9155 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx @@ -6,13 +6,13 @@ * Side Public License, v 1. */ -import React, { useMemo } from 'react'; +import React, { useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiText, EuiSpacer, EuiLink, EuiTitle } from '@elastic/eui'; +import { EuiLink, EuiSpacer, EuiText, EuiTitle, EuiLoadingSpinner } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { DataViewField, DataView } from '@kbn/data-views-plugin/public'; +import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { DiscoverFieldBucket } from './discover_field_bucket'; -import { Bucket } from './types'; +import { Bucket, FieldDetails } from './types'; import { getDetails, isValidFieldDetails } from './get_details'; import { FetchStatus } from '../../../../types'; import { DataDocuments$ } from '../../../services/discover_data_state_container'; @@ -33,12 +33,30 @@ export function DiscoverFieldDetails({ dataView, onAddFilter, }: DiscoverFieldDetailsProps) { - const details = useMemo(() => { - const data = documents$.getValue(); - const documents = data.fetchStatus === FetchStatus.COMPLETE ? data.result : undefined; - return getDetails(field, documents, dataView); - }, [field, documents$, dataView]); + const [detailsState, setDetailsState] = useState<{ + details?: FieldDetails; + loaded: boolean; + }>(); + useEffect(() => { + const subscription = documents$.subscribe((data) => { + if (data.fetchStatus === FetchStatus.COMPLETE) { + setDetailsState({ details: getDetails(field, data.result, dataView), loaded: true }); + } else { + setDetailsState({ details: undefined, loaded: data.fetchStatus !== FetchStatus.LOADING }); + } + }); + + return () => { + subscription.unsubscribe(); + }; + }, [documents$, setDetailsState, dataView, field]); + + if (!detailsState?.loaded) { + return ; + } + + const details = detailsState?.details; if (!details) { return null; } diff --git a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx index f8aae447c5c98..bf4b608a3c017 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx @@ -199,9 +199,9 @@ export const DiscoverTopNav = ({ }; const updateSavedQueryId = (newSavedQueryId: string | undefined) => { - const { appState, setAppState } = stateContainer; + const { appState } = stateContainer; if (newSavedQueryId) { - setAppState({ savedQuery: newSavedQueryId }); + appState.update({ savedQuery: newSavedQueryId }); } else { // remove savedQueryId from state const newState = { diff --git a/src/plugins/discover/public/application/main/discover_main_app.tsx b/src/plugins/discover/public/application/main/discover_main_app.tsx index 50caf6aa15e68..828558cec13ae 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.tsx @@ -57,7 +57,6 @@ export function DiscoverMainApp(props: DiscoverMainProps) { resetSavedSearch, searchSource, stateContainer, - searchSessionManager, updateDataViewList, } = useDiscoverState({ services, @@ -119,7 +118,6 @@ export function DiscoverMainApp(props: DiscoverMainProps) { stateContainer={stateContainer} persistDataView={persistDataView} updateAdHocDataViewId={updateAdHocDataViewId} - searchSessionManager={searchSessionManager} updateDataViewList={updateDataViewList} /> diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 1170629142dae..fe9612af0ca9f 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -120,7 +120,7 @@ export function useDiscoverState({ * or dataView / savedSearch switch */ useEffect(() => { - const stopSync = stateContainer.initializeAndSync(dataView, filterManager, data); + const stopSync = stateContainer.actions.initializeAndSync(dataView, filterManager, data); setState(stateContainer.appState.getState()); return () => stopSync(); @@ -213,7 +213,7 @@ export function useDiscoverState({ */ useEffect(() => { if (dataView && (!dataView.isTimeBased() || dataView.type === DataViewType.ROLLUP)) { - stateContainer.pauseAutoRefreshInterval(); + stateContainer.actions.pauseAutoRefreshInterval(); } }, [dataView, stateContainer]); @@ -226,7 +226,6 @@ export function useDiscoverState({ stateContainer, persistDataView, updateAdHocDataViewId, - searchSessionManager, updateDataViewList, }; } diff --git a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts index b596e2bc06c40..7ac2fb6ef7916 100644 --- a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts @@ -28,7 +28,7 @@ function getHookProps( const replaceUrlState = jest.fn(); const stateContainer = getDiscoverStateMock({ isTimeBased: true }); stateContainer.appState.replaceUrlState = replaceUrlState; - stateContainer.setAppState({ columns: [] }); + stateContainer.appState.update({ columns: [] }); stateContainer.internalState.transitions.setSavedDataViews([dataViewMock as DataViewListItem]); const msgLoading = { diff --git a/src/plugins/discover/public/application/main/services/discover_state.test.ts b/src/plugins/discover/public/application/main/services/discover_state.test.ts index a61808d433b5b..c2efd78b24c8f 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.test.ts @@ -48,7 +48,7 @@ describe('Test discover state', () => { stopSync = () => {}; }); test('setting app state and syncing to URL', async () => { - state.setAppState({ index: 'modified' }); + state.appState.update({ index: 'modified' }); state.kbnUrlStateStorage.kbnUrlControls.flush(); expect(getCurrentUrl()).toMatchInlineSnapshot( `"/#?_a=(columns:!(default_column),index:modified,interval:auto,sort:!())"` @@ -72,23 +72,23 @@ describe('Test discover state', () => { }); test('isAppStateDirty returns whether the current state has changed', async () => { - state.setAppState({ index: 'modified' }); + state.appState.update({ index: 'modified' }); expect(state.appState.hasChanged()).toBeTruthy(); state.appState.resetInitialState(); expect(state.appState.hasChanged()).toBeFalsy(); }); test('getPreviousAppState returns the state before the current', async () => { - state.setAppState({ index: 'first' }); + state.appState.update({ index: 'first' }); const stateA = state.appState.getState(); - state.setAppState({ index: 'second' }); + state.appState.update({ index: 'second' }); expect(state.appState.getPrevious()).toEqual(stateA); }); test('pauseAutoRefreshInterval sets refreshInterval.pause to true', async () => { history.push('/#?_g=(refreshInterval:(pause:!f,value:5000))'); expect(getCurrentUrl()).toBe('/#?_g=(refreshInterval:(pause:!f,value:5000))'); - await state.pauseAutoRefreshInterval(); + await state.actions.pauseAutoRefreshInterval(); expect(getCurrentUrl()).toBe('/#?_g=(refreshInterval:(pause:!t,value:5000))'); }); }); diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 934c599be785f..1a6350f865ef4 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -73,26 +73,14 @@ export interface DiscoverStateContainer { * Data fetching related state **/ dataState: DataStateContainer; - /** - * Initialize state with filters and query, start state syncing - */ - initializeAndSync: ( - dataView: DataView, - filterManager: FilterManager, - data: DataPublicPluginStart - ) => () => void; - /** - * Set app state to with a partial new app state - */ - setAppState: (newState: Partial) => void; - /** - * Pause the auto refresh interval without pushing an entry to history - */ - pauseAutoRefreshInterval: () => Promise; /** * functions executed by UI */ actions: { + /** + * Pause the auto refresh interval without pushing an entry to history + */ + pauseAutoRefreshInterval: () => Promise; /** * Set the currently selected data view */ @@ -132,6 +120,14 @@ export interface DiscoverStateContainer { * @param dataView */ replaceAdHocDataViewWithId: (id: string, dataView: DataView) => void; + /** + * Initialize state with filters and query, start state syncing + */ + initializeAndSync: ( + dataView: DataView, + filterManager: FilterManager, + data: DataPublicPluginStart + ) => () => void; }; } @@ -214,6 +210,7 @@ export function getDiscoverStateContainer({ ); return { fallback: !nextDataViewData.stateValFound, dataView: nextDataView }; }; + const initializeAndSync = () => appStateContainer.initAndSync(savedSearch); return { kbnUrlStateStorage: stateStorage, @@ -221,10 +218,8 @@ export function getDiscoverStateContainer({ internalState: internalStateContainer, dataState: dataStateContainer, searchSessionManager, - setAppState: (newPartial: AppState) => appStateContainer.update(newPartial), - pauseAutoRefreshInterval, - initializeAndSync: () => appStateContainer.initAndSync(savedSearch), actions: { + pauseAutoRefreshInterval, setDataView, loadAndResolveDataView, loadDataViewList, @@ -232,6 +227,7 @@ export function getDiscoverStateContainer({ appendAdHocDataViews, replaceAdHocDataViewWithId, removeAdHocDataViewById, + initializeAndSync, }, }; } diff --git a/src/plugins/discover/public/components/doc_table/actions/columns.ts b/src/plugins/discover/public/components/doc_table/actions/columns.ts index b6438a2e1cdd1..75c52356c88fb 100644 --- a/src/plugins/discover/public/components/doc_table/actions/columns.ts +++ b/src/plugins/discover/public/components/doc_table/actions/columns.ts @@ -8,8 +8,8 @@ import { Capabilities, IUiSettingsClient } from '@kbn/core/public'; import { DataViewsContract } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; +import { DiscoverAppStateContainer } from '../../../application/main/services/discover_app_state_container'; import { SORT_DEFAULT_ORDER_SETTING } from '../../../../common'; -import { DiscoverStateContainer as DiscoverGetStateReturn } from '../../../application/main/services/discover_state'; import { GetStateReturn as ContextGetStateReturn } from '../../../application/context/services/context_state'; import { popularizeField } from '../../../utils/popularize_field'; @@ -70,7 +70,7 @@ export function getStateColumnActions({ dataView: DataView; dataViews: DataViewsContract; useNewFieldsApi: boolean; - setAppState: DiscoverGetStateReturn['setAppState'] | ContextGetStateReturn['setAppState']; + setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState']; columns?: string[]; sort: string[][] | undefined; }) { diff --git a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx index 2eca5a90b9fbf..62fdccc0f4642 100644 --- a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx +++ b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx @@ -7,35 +7,33 @@ */ import React from 'react'; +import { EuiIcon, EuiLoadingSpinner } from '@elastic/eui'; import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { dataViewMock } from '../../__mocks__/data_view'; -import { DocTableWrapper } from './doc_table_wrapper'; +import { DocTableWrapper, DocTableWrapperProps } from './doc_table_wrapper'; import { discoverServiceMock } from '../../__mocks__/services'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '../../utils/build_data_record'; import { EsHitRecord } from '../../types'; describe('Doc table component', () => { - const mountComponent = (rows?: EsHitRecord[]) => { + const mountComponent = (customProps?: Partial) => { const props = { columns: ['_source'], dataView: dataViewMock, - rows: ( - rows || [ - { - _index: 'mock_index', - _id: '1', - _score: 1, - fields: [ - { - timestamp: '2020-20-01T12:12:12.123', - }, - ], - _source: { message: 'mock_message', bytes: 20 }, - } as EsHitRecord, - ] - ).map((row) => buildDataTableRecord(row, dataViewMock)), - + rows: [ + { + _index: 'mock_index', + _id: '1', + _score: 1, + fields: [ + { + timestamp: '2020-20-01T12:12:12.123', + }, + ], + _source: { message: 'mock_message', bytes: 20 }, + } as EsHitRecord, + ].map((row) => buildDataTableRecord(row, dataViewMock)), sort: [['order_date', 'desc']], isLoading: false, searchDescription: '', @@ -49,6 +47,7 @@ describe('Doc table component', () => { render: () => { return
mock
; }, + ...(customProps || {}), }; return mountWithIntl( @@ -66,9 +65,16 @@ describe('Doc table component', () => { }); it('should render error fallback if rows array is empty', () => { - const component = mountComponent([]); + const component = mountComponent({ rows: [], isLoading: false }); + expect(findTestSubject(component, 'discoverDocTable').exists()).toBeTruthy(); + expect(findTestSubject(component, 'docTable').exists()).toBeFalsy(); + expect(component.find('.kbnDocTable__error').find(EuiIcon).exists()).toBeTruthy(); + }); + + it('should render loading indicator', () => { + const component = mountComponent({ rows: [], isLoading: true }); expect(findTestSubject(component, 'discoverDocTable').exists()).toBeTruthy(); expect(findTestSubject(component, 'docTable').exists()).toBeFalsy(); - expect(component.find('.kbnDocTable__error').exists()).toBeTruthy(); + expect(component.find('.kbnDocTable__error').find(EuiLoadingSpinner).exists()).toBeTruthy(); }); }); diff --git a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx index bf940c79be545..9d4d40242ab25 100644 --- a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx +++ b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx @@ -7,7 +7,7 @@ */ import React, { forwardRef, useCallback, useMemo } from 'react'; -import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiIcon, EuiLoadingSpinner, EuiSpacer, EuiText } from '@elastic/eui'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import type { SortOrder } from '@kbn/saved-search-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -218,12 +218,22 @@ export const DocTableWrapper = forwardRef( {!rows.length && (
- - - + {isLoading ? ( + <> + + + + + ) : ( + <> + + + + + )}
)} diff --git a/src/plugins/discover/public/hooks/use_data_grid_columns.ts b/src/plugins/discover/public/hooks/use_data_grid_columns.ts index c693117916d71..22fc8e9836888 100644 --- a/src/plugins/discover/public/hooks/use_data_grid_columns.ts +++ b/src/plugins/discover/public/hooks/use_data_grid_columns.ts @@ -11,7 +11,7 @@ import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public' import { Capabilities, IUiSettingsClient } from '@kbn/core/public'; import { isEqual } from 'lodash'; -import { DiscoverStateContainer as DiscoverGetStateReturn } from '../application/main/services/discover_state'; +import { DiscoverAppStateContainer } from '../application/main/services/discover_app_state_container'; import { GetStateReturn as ContextGetStateReturn } from '../application/context/services/context_state'; import { getStateColumnActions } from '../components/doc_table/actions/columns'; @@ -21,7 +21,7 @@ interface UseColumnsProps { dataView: DataView; dataViews: DataViewsContract; useNewFieldsApi: boolean; - setAppState: DiscoverGetStateReturn['setAppState'] | ContextGetStateReturn['setAppState']; + setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState']; columns?: string[]; sort?: string[][]; } diff --git a/src/plugins/files/common/default_image_file_kind.ts b/src/plugins/files/common/default_image_file_kind.ts index 2fd2812e6f17b..9e20f2f058747 100644 --- a/src/plugins/files/common/default_image_file_kind.ts +++ b/src/plugins/files/common/default_image_file_kind.ts @@ -6,30 +6,14 @@ * Side Public License, v 1. */ -import { FileKind } from './types'; +import { FileKindBase } from '@kbn/shared-ux-file-types'; -const id = 'defaultImage' as const; -const tag = 'files:defaultImage' as const; -const tags = [`access:${tag}`]; -const tenMebiBytes = 1024 * 1024 * 10; +export const id = 'defaultImage' as const; +export const tag = 'files:defaultImage' as const; +export const tags = [`access:${tag}`]; +export const maxSize = 1024 * 1024 * 10; -/** - * A file kind that is available to all plugins to use for uploading images - * intended to be reused across Kibana. - */ -export const defaultImageFileKind: FileKind = { +export const kind: FileKindBase = { id, - maxSizeBytes: tenMebiBytes, - blobStoreSettings: {}, - // tried using "image/*" but it did not work with the HTTP endpoint (got 415 Unsupported Media Type) allowedMimeTypes: ['image/png', 'image/jpeg', 'image/webp', 'image/avif'], - http: { - create: { tags }, - delete: { tags }, - download: { tags }, - getById: { tags }, - list: { tags }, - share: { tags }, - update: { tags }, - }, }; diff --git a/src/plugins/files/common/file_kinds_registry/index.ts b/src/plugins/files/common/file_kinds_registry/index.ts index afed906bd0aa3..58e2f51bca6a0 100644 --- a/src/plugins/files/common/file_kinds_registry/index.ts +++ b/src/plugins/files/common/file_kinds_registry/index.ts @@ -6,36 +6,39 @@ * Side Public License, v 1. */ -import { createGetterSetter } from '@kbn/kibana-utils-plugin/common'; import assert from 'assert'; -import { FileKind } from '..'; +import { createGetterSetter } from '@kbn/kibana-utils-plugin/common'; +import type { FileKindBase } from '@kbn/shared-ux-file-types'; +import type { FileKind } from '../types'; -export interface FileKindsRegistry { +export interface FileKindsRegistry { /** * Register a new file kind. */ - register(fileKind: FileKind): void; + register(fileKind: FK): void; /** * Gets a {@link FileKind} or throws. */ - get(id: string): FileKind; + get(id: string): FK; /** * Return all registered {@link FileKind}s. */ - getAll(): FileKind[]; + getAll(): FK[]; } /** * @internal */ -export class FileKindsRegistryImpl implements FileKindsRegistry { - constructor(private readonly onRegister?: (fileKind: FileKind) => void) {} +export class FileKindsRegistryImpl + implements FileKindsRegistry +{ + constructor(private readonly onRegister?: (fileKind: FK) => void) {} - private readonly fileKinds = new Map(); + private readonly fileKinds = new Map(); - register(fileKind: FileKind) { + register(fileKind: FK) { if (this.fileKinds.get(fileKind.id)) { throw new Error(`File kind "${fileKind.id}" already registered.`); } @@ -50,13 +53,13 @@ export class FileKindsRegistryImpl implements FileKindsRegistry { this.onRegister?.(fileKind); } - get(id: string): FileKind { + get(id: string): FK { const fileKind = this.fileKinds.get(id); assert(fileKind, `File kind with id "${id}" not found.`); return fileKind; } - getAll(): FileKind[] { + getAll(): FK[] { return Array.from(this.fileKinds.values()); } } diff --git a/src/plugins/files/common/index.ts b/src/plugins/files/common/index.ts index 05d32a0645a0d..96319e9651dc2 100755 --- a/src/plugins/files/common/index.ts +++ b/src/plugins/files/common/index.ts @@ -7,11 +7,11 @@ */ export { FILE_SO_TYPE, PLUGIN_ID, PLUGIN_NAME, ES_FIXED_SIZE_INDEX_BLOB_STORE } from './constants'; -export { defaultImageFileKind } from './default_image_file_kind'; export type { File, FileKind, + FileKindBrowser, FileJSON, FileShare, FileStatus, @@ -29,3 +29,6 @@ export type { FileShareJSONWithToken, UpdatableFileShareMetadata, } from './types'; + +import * as DefaultFileKind from './default_image_file_kind'; +export { DefaultFileKind }; diff --git a/src/plugins/files/common/types.ts b/src/plugins/files/common/types.ts index b0f9b7e0b9b6f..c0cf5dacf687a 100644 --- a/src/plugins/files/common/types.ts +++ b/src/plugins/files/common/types.ts @@ -9,11 +9,20 @@ import type { SavedObject } from '@kbn/core/server'; import type { Observable } from 'rxjs'; import type { Readable } from 'stream'; -import type { FileJSON, FileStatus, FileMetadata } from '@kbn/shared-ux-file-types'; +import type { + FileJSON, + FileStatus, + FileMetadata, + FileShare, + FileShareJSON, + FileKindBase, + FileShareJSONWithToken, +} from '@kbn/shared-ux-file-types'; import type { ES_FIXED_SIZE_INDEX_BLOB_STORE } from './constants'; export type { - FileKind, + FileKindBase, + FileKindBrowser, FileJSON, FileStatus, FileMetadata, @@ -23,96 +32,107 @@ export type { FileImageMetadata, } from '@kbn/shared-ux-file-types'; -/** - * Values for paginating through results. - */ -export interface Pagination { - /** - * Page of results. - */ - page?: number; - /** - * Number of results per page. - */ - perPage?: number; -} - -/** - * An {@link SavedObject} containing a file object (i.e., metadata only). - */ -export type FileSavedObject = SavedObject>; - -/** - * The set of file metadata that can be updated. - */ -export type UpdatableFileMetadata = Pick, 'meta' | 'alt' | 'name'>; - -/** - * Data stored with a file share object +/* + * A descriptor of meta values associated with a set or "kind" of files. + * + * @note In order to use the file service consumers must register a {@link FileKind} + * in the {@link FileKindsRegistry}. */ -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type FileShare = { +export interface FileKind extends FileKindBase { /** - * ISO timestamp of when the file share was created. + * Max file contents size, in bytes. Can be customized per file using the + * {@link FileJSON} object. This is enforced on the server-side as well as + * in the upload React component. + * + * @default 4MiB */ - created: string; + maxSizeBytes?: number | ((file: FileJSON) => number); /** - * Secret token used to access the associated file. + * Blob store specific settings that enable configuration of storage + * details. */ - token: string; + blobStoreSettings?: BlobStorageSettings; /** - * Human friendly name for this share token. + * Specify which HTTP routes to create for the file kind. + * + * You can always create your own HTTP routes for working with files but + * this interface allows you to expose basic CRUD operations, upload, download + * and sharing of files over a RESTful-like interface. + * + * @note The public {@link FileClient} uses these endpoints. */ - name?: string; + http: { + /** + * Expose file creation (and upload) over HTTP. + */ + create?: HttpEndpointDefinition; + /** + * Expose file updates over HTTP. + */ + update?: HttpEndpointDefinition; + /** + * Expose file deletion over HTTP. + */ + delete?: HttpEndpointDefinition; + /** + * Expose "get by ID" functionality over HTTP. + */ + getById?: HttpEndpointDefinition; + /** + * Expose the ability to list all files of this kind over HTTP. + */ + list?: HttpEndpointDefinition; + /** + * Expose the ability to download a file's contents over HTTP. + */ + download?: HttpEndpointDefinition; + /** + * Expose file share functionality over HTTP. + */ + share?: HttpEndpointDefinition; + }; +} +/** Definition for an endpoint that the File's service will generate */ +interface HttpEndpointDefinition { /** - * The unix timestamp (in milliseconds) this file share will expire. + * Specify the tags for this endpoint. + * + * @example + * // This will enable access control to this endpoint for users that can access "myApp" only. + * { tags: ['access:myApp'] } * - * TODO: in future we could add a special value like "forever", but this should - * not be the default. */ - valid_until: number; -}; + tags: string[]; +} /** - * Attributes of a file that represent a serialised version of the file. + * Values for paginating through results. */ -export interface FileShareJSON { - /** - * Unique ID share instance - */ - id: string; - /** - * ISO timestamp the share was created - */ - created: FileShare['created']; - /** - * Unix timestamp (in milliseconds) of when this share expires - */ - validUntil: FileShare['valid_until']; +export interface Pagination { /** - * A user-friendly name for the file share + * Page of results. */ - name?: FileShare['name']; + page?: number; /** - * The ID of the file this share is linked to + * Number of results per page. */ - fileId: string; + perPage?: number; } /** - * A version of the file share with a token included. - * - * @note This should only be shown when the file share is first created + * An {@link SavedObject} containing a file object (i.e., metadata only). */ -export type FileShareJSONWithToken = FileShareJSON & { - /** - * Secret token that can be used to access files - */ - token: string; -}; +export type FileSavedObject = SavedObject>; + +/** + * The set of file metadata that can be updated. + */ +export type UpdatableFileMetadata = Pick, 'meta' | 'alt' | 'name'>; + +export type { FileShare, FileShareJSON, FileShareJSONWithToken }; /** * Set of attributes that can be updated in a file share. diff --git a/src/plugins/files/public/files_client/files_client.ts b/src/plugins/files/public/files_client/files_client.ts index 9044ab58cbf7e..f091f3317b4b1 100644 --- a/src/plugins/files/public/files_client/files_client.ts +++ b/src/plugins/files/public/files_client/files_client.ts @@ -7,8 +7,9 @@ */ import type { HttpStart } from '@kbn/core/public'; +import type { FileKindBrowser } from '@kbn/shared-ux-file-types'; import type { ScopedFilesClient, FilesClient } from '../types'; -import { getFileKindsRegistry } from '../../common/file_kinds_registry'; +import { FileKindsRegistryImpl } from '../../common/file_kinds_registry'; import { API_BASE_PATH, FILES_API_BASE_PATH, @@ -56,6 +57,11 @@ export const apiRoutes = { * Arguments to create a new {@link FileClient}. */ export interface Args { + /** + * Registry of file kinds. + */ + registry: FileKindsRegistryImpl; + /** * The http start service from core. */ @@ -81,9 +87,11 @@ const commonBodyHeaders = { export function createFilesClient(args: Args): FilesClient; export function createFilesClient(scopedArgs: ScopedArgs): ScopedFilesClient; export function createFilesClient({ + registry, http, fileKind: scopedFileKind, }: { + registry: FileKindsRegistryImpl; http: HttpStart; fileKind?: string; }): FilesClient | ScopedFilesClient { @@ -172,7 +180,7 @@ export function createFilesClient({ return http.get(apiRoutes.getPublicDownloadRoute(fileName), { query: { token } }); }, getFileKind(id: string) { - return getFileKindsRegistry().get(id); + return registry.get(id); }, }; return api; diff --git a/src/plugins/files/public/index.ts b/src/plugins/files/public/index.ts index 168780bd92380..d4970fe4f3bff 100644 --- a/src/plugins/files/public/index.ts +++ b/src/plugins/files/public/index.ts @@ -7,7 +7,6 @@ */ import { FilesPlugin } from './plugin'; -export { defaultImageFileKind } from '../common/default_image_file_kind'; export type { FilesSetup, FilesStart } from './plugin'; export type { FilesClient, diff --git a/src/plugins/files/public/plugin.ts b/src/plugins/files/public/plugin.ts index 57f17fd6a3753..54646e9199f9a 100644 --- a/src/plugins/files/public/plugin.ts +++ b/src/plugins/files/public/plugin.ts @@ -7,16 +7,12 @@ */ import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; -import { - getFileKindsRegistry, - setFileKindsRegistry, - FileKindsRegistryImpl, -} from '../common/file_kinds_registry'; import type { FilesClient, FilesClientFactory } from './types'; +import { FileKindsRegistryImpl } from '../common/file_kinds_registry'; import { createFilesClient } from './files_client'; -import { FileKind } from '../common'; -import { registerDefaultFileKinds } from '../common/register_default_file_kinds'; +import { FileKindBrowser } from '../common'; import { ScopedFilesClient } from '.'; +import * as DefaultImageFileKind from '../common/default_image_file_kind'; /** * Public setup-phase contract @@ -24,7 +20,7 @@ import { ScopedFilesClient } from '.'; export interface FilesSetup { /** * A factory for creating an {@link FilesClient} instance. This requires a - * registered {@link FileKind}. + * registered {@link FileKindBrowser}. * * @track-adoption */ @@ -36,7 +32,7 @@ export interface FilesSetup { * * @param {FileKind} fileKind - the file kind to register */ - registerFileKind(fileKind: FileKind): void; + registerFileKind(fileKind: FileKindBrowser): void; } export type FilesStart = Pick; @@ -45,26 +41,35 @@ export type FilesStart = Pick; * Bringing files to Kibana */ export class FilesPlugin implements Plugin { - private filesClientFactory: undefined | FilesClientFactory; - - constructor() { - setFileKindsRegistry(new FileKindsRegistryImpl()); - } + private registry = new FileKindsRegistryImpl(); + private filesClientFactory?: FilesClientFactory; setup(core: CoreSetup): FilesSetup { + this.registry.register({ + ...DefaultImageFileKind.kind, + maxSizeBytes: DefaultImageFileKind.maxSize, + }); + this.filesClientFactory = { - asScoped(fileKind: string) { - return createFilesClient({ fileKind, http: core.http }) as ScopedFilesClient; + asScoped: (fileKind: string) => { + return createFilesClient({ + registry: this.registry, + fileKind, + http: core.http, + }) as ScopedFilesClient; }, - asUnscoped() { - return createFilesClient({ http: core.http }) as FilesClient; + asUnscoped: () => { + return createFilesClient({ + registry: this.registry, + http: core.http, + }) as FilesClient; }, }; - registerDefaultFileKinds(); + return { filesClientFactory: this.filesClientFactory, - registerFileKind: (fileKind: FileKind) => { - getFileKindsRegistry().register(fileKind); + registerFileKind: (fileKind: FileKindBrowser) => { + this.registry.register(fileKind); }, }; } diff --git a/src/plugins/files/server/file/file.ts b/src/plugins/files/server/file/file.ts index d8f246d864882..fd5a27fd1bfaa 100644 --- a/src/plugins/files/server/file/file.ts +++ b/src/plugins/files/server/file/file.ts @@ -71,7 +71,7 @@ export class File implements IFile { } private upload(content: Readable): Observable<{ size: number }> { - return defer(() => this.fileClient.upload(this.id, content)); + return defer(() => this.fileClient.upload(this.metadata, content)); } public async uploadContent( diff --git a/src/plugins/files/server/file_client/create_es_file_client.ts b/src/plugins/files/server/file_client/create_es_file_client.ts index 1fb14b1fdfbba..90c5ef8893b14 100644 --- a/src/plugins/files/server/file_client/create_es_file_client.ts +++ b/src/plugins/files/server/file_client/create_es_file_client.ts @@ -27,15 +27,15 @@ export interface CreateEsFileClientArgs { */ blobStorageIndex: string; /** - * An elasticsearch client that will be used to interact with the cluster + * An elasticsearch client that will be used to interact with the cluster. */ elasticsearchClient: ElasticsearchClient; /** - * The maximum file size to be write + * The maximum file size to be written. */ maxSizeBytes?: number; /** - * A logger for debuggin purposes + * A logger for debugging purposes. */ logger: Logger; } diff --git a/src/plugins/files/server/file_client/file_client.ts b/src/plugins/files/server/file_client/file_client.ts index 8e1a8d2fdb933..f08648aac107b 100644 --- a/src/plugins/files/server/file_client/file_client.ts +++ b/src/plugins/files/server/file_client/file_client.ts @@ -43,6 +43,8 @@ import { export type UploadOptions = Omit; +const fourMiB = 4 * 1024 * 1024; + export function createFileClient({ fileKindDescriptor, auditLogger, @@ -211,17 +213,28 @@ export class FileClientImpl implements FileClient { * @param options - Options for the upload */ public upload = async ( - id: string, + file: FileJSON, rs: Readable, options?: UploadOptions ): ReturnType => { + const { maxSizeBytes } = this.fileKindDescriptor; + const { transforms = [], ...blobOptions } = options || {}; + + let maxFileSize: number = typeof maxSizeBytes === 'number' ? maxSizeBytes : fourMiB; + + if (typeof maxSizeBytes === 'function') { + const sizeLimitPerFile = maxSizeBytes(file); + if (typeof sizeLimitPerFile === 'number') { + maxFileSize = sizeLimitPerFile; + } + } + + transforms.push(enforceMaxByteSizeTransform(maxFileSize)); + return this.blobStorageClient.upload(rs, { - ...options, - transforms: [ - ...(options?.transforms || []), - enforceMaxByteSizeTransform(this.fileKindDescriptor.maxSizeBytes ?? Infinity), - ], - id, + ...blobOptions, + transforms, + id: file.id, }); }; diff --git a/src/plugins/files/server/integration_tests/file_service.test.ts b/src/plugins/files/server/integration_tests/file_service.test.ts index 10aa11290a3e9..25d7f463de03a 100644 --- a/src/plugins/files/server/integration_tests/file_service.test.ts +++ b/src/plugins/files/server/integration_tests/file_service.test.ts @@ -63,7 +63,9 @@ describe('FileService', () => { }); fileKindsRegistry.register({ id: fileKindTinyFiles, - maxSizeBytes: 10, + maxSizeBytes: (file) => { + return file.mimeType === 'text/json' ? 3 : 10; + }, http: {}, }); esClient = coreStart.elasticsearch.client.asInternalUser; @@ -263,7 +265,7 @@ describe('FileService', () => { expect(updatedFile2.data.alt).toBe(updatableFields.alt); }); - it('enforces max size settings', async () => { + it('enforces file kind max size settings', async () => { const file = await createDisposableFile({ fileKind: fileKindTinyFiles, name: 'test' }); const tinyContent = Readable.from(['ok']); await file.uploadContent(tinyContent); @@ -275,6 +277,26 @@ describe('FileService', () => { ); }); + it('enforces per file max size settings, using mime type', async () => { + const file = await createDisposableFile({ + fileKind: fileKindTinyFiles, + name: 'test', + mime: 'text/mime', + }); + const tinyContent = Readable.from(['ok ok ok']); + await file.uploadContent(tinyContent); + + const file2 = await createDisposableFile({ + fileKind: fileKindTinyFiles, + name: 'test', + mime: 'text/json', + }); + const notSoTinyContent = Readable.from(['[123]']); + await expect(() => file2.uploadContent(notSoTinyContent)).rejects.toThrow( + new Error('Maximum of 3 bytes exceeded') + ); + }); + describe('ES blob integration and file kinds', () => { it('passes blob store settings', async () => { const file = await createDisposableFile({ fileKind: fileKindNonDefault, name: 'test' }); diff --git a/src/plugins/files/server/plugin.ts b/src/plugins/files/server/plugin.ts index 1680512ded3d2..ba63e08b2ed21 100755 --- a/src/plugins/files/server/plugin.ts +++ b/src/plugins/files/server/plugin.ts @@ -21,7 +21,6 @@ import { getFileKindsRegistry, FileKindsRegistryImpl, } from '../common/file_kinds_registry'; -import { registerDefaultFileKinds } from '../common/register_default_file_kinds'; import { BlobStorageService } from './blob_storage_service'; import { FileServiceFactory } from './file_service'; @@ -35,6 +34,7 @@ import type { import type { FilesRequestHandlerContext, FilesRouter } from './routes/types'; import { registerRoutes, registerFileKindRoutes } from './routes'; import { Counters, registerUsageCollector } from './usage'; +import * as DefaultImageKind from '../common/default_image_file_kind'; export class FilesPlugin implements Plugin { private static analytics?: AnalyticsServiceStart; @@ -92,8 +92,7 @@ export class FilesPlugin implements Plugin this.fileServiceFactory?.asInternal(), }); - // Now that everything is set up: - registerDefaultFileKinds(); + this.registerDefaultImageFileKind(); return { registerFileKind(fileKind) { @@ -125,4 +124,21 @@ export class FilesPlugin implements Plugin = async ({ files, fileKind }, req, try { await file.uploadContent(stream as Readable, abort$); } catch (e) { + if (e instanceof MaxByteSizeExceededError) { + return res.customError({ + statusCode: 413, + }); + } + if ( e instanceof fileErrors.ContentAlreadyUploadedError || e instanceof fileErrors.UploadInProgressError @@ -81,8 +88,6 @@ export const handler: CreateHandler = async ({ files, fileKind }, req, return res.ok({ body }); }; -const fourMiB = 4 * 1024 * 1024; - export function register(fileKindRouter: FileKindRouter, fileKind: FileKind) { if (fileKind.http.create) { fileKindRouter[method]( @@ -97,7 +102,12 @@ export function register(fileKindRouter: FileKindRouter, fileKind: FileKind) { output: 'stream', parse: false, accepts: fileKind.allowedMimeTypes ?? 'application/octet-stream', - maxBytes: fileKind.maxSizeBytes ?? fourMiB, + + // This is set to 10 GiB because the actual file size limit is + // enforced by the file service. This is just a limit on the + // size of the HTTP request body, but the file service will throw + // 413 errors if the file size is larger than expected. + maxBytes: 10 * 1024 * 1024 * 1024, }, }, }, diff --git a/src/plugins/image_embeddable/public/imports.ts b/src/plugins/image_embeddable/public/imports.ts index 59acef5e42633..923ff8bf39b22 100644 --- a/src/plugins/image_embeddable/public/imports.ts +++ b/src/plugins/image_embeddable/public/imports.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { FileKind } from '@kbn/shared-ux-file-types'; -import { defaultImageFileKind } from '@kbn/files-plugin/common'; +import { DefaultFileKind } from '@kbn/files-plugin/common'; export type { FilesClient, @@ -27,4 +26,4 @@ export type { ApplicationStart, OverlayStart, ThemeServiceStart } from '@kbn/cor export type { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/public'; -export const imageEmbeddableFileKind: FileKind = defaultImageFileKind; +export const imageEmbeddableFileKind = DefaultFileKind.kind; diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index 816f3a7635a12..172f3227d479a 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -47,6 +47,7 @@ export { export { useExecutionContext } from './use_execution_context'; export type { ToolbarButtonProps } from './toolbar_button'; +/** @deprecated ToolbarButton - use `ToolbarButton` from `@kbn/shared-ux-button-toolbar` */ export { POSITIONS, WEIGHTS, TOOLBAR_BUTTON_SIZES, ToolbarButton } from './toolbar_button'; export { Route } from './router'; diff --git a/src/plugins/kibana_react/public/notifications/create_notifications.test.tsx b/src/plugins/kibana_react/public/notifications/create_notifications.test.tsx index 0b2c0a0478d53..0876472d89f1b 100644 --- a/src/plugins/kibana_react/public/notifications/create_notifications.test.tsx +++ b/src/plugins/kibana_react/public/notifications/create_notifications.test.tsx @@ -162,7 +162,7 @@ test('can display success, warning and danger toasts', () => { expect(notifications.toasts.add.mock.calls[2][0]).toMatchInlineSnapshot(` Object { "color": "danger", - "iconType": "alert", + "iconType": "error", "onClose": undefined, "text": MountPoint { "reactNode": , diff --git a/src/plugins/kibana_react/public/notifications/create_notifications.tsx b/src/plugins/kibana_react/public/notifications/create_notifications.tsx index 8eb16a5580ab3..ab2cccf7655a3 100644 --- a/src/plugins/kibana_react/public/notifications/create_notifications.tsx +++ b/src/plugins/kibana_react/public/notifications/create_notifications.tsx @@ -40,7 +40,7 @@ export const createNotifications = (services: KibanaServices): KibanaReactNotifi show({ color: 'warning', iconType: 'help', ...input }); const danger: KibanaReactNotifications['toasts']['danger'] = (input) => - show({ color: 'danger', iconType: 'alert', ...input }); + show({ color: 'danger', iconType: 'error', ...input }); const notifications: KibanaReactNotifications = { toasts: { diff --git a/src/plugins/presentation_util/public/components/field_picker/field_picker.scss b/src/plugins/presentation_util/public/components/field_picker/field_picker.scss index a06c469e713bf..bbb3e8eb44be3 100644 --- a/src/plugins/presentation_util/public/components/field_picker/field_picker.scss +++ b/src/plugins/presentation_util/public/components/field_picker/field_picker.scss @@ -1,17 +1,4 @@ -.presFieldPicker__fieldButton { - background: $euiColorEmptyShade; -} .presFieldPickerFieldButtonActive { - box-shadow: 0 0 0 2px $euiColorPrimary; -} - -.presFieldPicker__fieldPanel { - height: 300px; - overflow-y: scroll; -} - -.presFieldPicker__container--disabled { - opacity: .7; - pointer-events: none; + background-color: transparentize($euiColorPrimary, .9); } \ No newline at end of file diff --git a/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx b/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx index 3c8a084f2686b..3d6a42d7211a8 100644 --- a/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx +++ b/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx @@ -8,13 +8,14 @@ import classNames from 'classnames'; import { sortBy, uniq } from 'lodash'; -import React, { useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; -import { FieldButton, FieldIcon } from '@kbn/react-field'; +import React, { useEffect, useMemo, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FieldIcon } from '@kbn/react-field'; +import { EuiSelectable, EuiSelectableOption, EuiSpacer } from '@elastic/eui'; import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; -import { FieldSearch } from './field_search'; + +import { FieldTypeFilter } from './field_type_filter'; import './field_picker.scss'; @@ -31,115 +32,102 @@ export const FieldPicker = ({ filterPredicate, selectedFieldName, }: FieldPickerProps) => { - const [nameFilter, setNameFilter] = useState(''); const [typesFilter, setTypesFilter] = useState([]); + const [fieldSelectableOptions, setFieldSelectableOptions] = useState([]); - // Retrieve, filter, and sort fields from data view - const fields = dataView - ? sortBy( - dataView.fields - .filter( - (f) => - f.name.toLowerCase().includes(nameFilter.toLowerCase()) && - (typesFilter.length === 0 || typesFilter.includes(f.type as string)) - ) + const availableFields = useMemo( + () => + sortBy( + (dataView?.fields ?? []) + .filter((f) => typesFilter.length === 0 || typesFilter.includes(f.type as string)) .filter((f) => (filterPredicate ? filterPredicate(f) : true)), ['name'] - ) - : []; + ), + [dataView, filterPredicate, typesFilter] + ); + + useEffect(() => { + if (!dataView) return; + const options: EuiSelectableOption[] = (availableFields ?? []).map((field) => { + return { + key: field.name, + label: field.displayName ?? field.name, + className: classNames('presFieldPicker__fieldButton', { + presFieldPickerFieldButtonActive: field.name === selectedFieldName, + }), + 'data-test-subj': `field-picker-select-${field.name}`, + prepend: ( + + ), + }; + }); + setFieldSelectableOptions(options); + }, [availableFields, dataView, filterPredicate, selectedFieldName, typesFilter]); - const uniqueTypes = dataView - ? uniq( - dataView.fields - .filter((f) => (filterPredicate ? filterPredicate(f) : true)) - .map((f) => f.type as string) - ) - : []; + const uniqueTypes = useMemo( + () => + dataView + ? uniq( + dataView.fields + .filter((f) => (filterPredicate ? filterPredicate(f) : true)) + .map((f) => f.type as string) + ) + : [], + [dataView, filterPredicate] + ); + + const fieldTypeFilter = ( + setTypesFilter(types)} + fieldTypesValue={typesFilter} + availableFieldTypes={uniqueTypes} + /> + ); return ( - { + setFieldSelectableOptions(options); + if (!dataView || !changedOption.key) return; + const field = dataView.getFieldByName(changedOption.key); + if (field) onSelectField?.(field); + }} + searchProps={{ + 'data-test-subj': 'field-search-input', + placeholder: i18n.translate('presentationUtil.fieldSearch.searchPlaceHolder', { + defaultMessage: 'Search field names', + }), + }} + listProps={{ + isVirtualized: true, + showIcons: false, + bordered: true, + }} + height={300} > - - setNameFilter(val)} - searchValue={nameFilter} - onFieldTypesChange={(types) => setTypesFilter(types)} - fieldTypesValue={typesFilter} - availableFieldTypes={uniqueTypes} - /> - - - - {fields.length > 0 && ( - - {fields.map((f, i) => { - return ( - - { - onSelectField?.(f); - }} - isActive={f.name === selectedFieldName} - fieldName={f.name} - fieldIcon={} - /> - - ); - })} - - )} - {!dataView && ( - - - - - - - - )} - {dataView && fields.length === 0 && ( - - - - - - - - )} - - - + {(list, search) => ( + <> + {search} + + {fieldTypeFilter} + + {list} + + )} + ); }; diff --git a/src/plugins/presentation_util/public/components/field_picker/field_search.tsx b/src/plugins/presentation_util/public/components/field_picker/field_search.tsx deleted file mode 100644 index d3307f71988f1..0000000000000 --- a/src/plugins/presentation_util/public/components/field_picker/field_search.tsx +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiFieldSearch, - EuiFilterGroup, - EuiFlexGroup, - EuiFlexItem, - EuiPopover, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiOutsideClickDetector, - EuiFilterButton, - EuiSpacer, - EuiPopoverTitle, -} from '@elastic/eui'; -import { FieldIcon } from '@kbn/react-field'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import './field_search.scss'; - -export interface Props { - onSearchChange: (value: string) => void; - searchValue?: string; - - onFieldTypesChange: (value: string[]) => void; - fieldTypesValue: string[]; - - availableFieldTypes: string[]; -} - -export function FieldSearch({ - onSearchChange, - searchValue, - onFieldTypesChange, - fieldTypesValue, - availableFieldTypes, -}: Props) { - const searchPlaceholder = i18n.translate('presentationUtil.fieldSearch.searchPlaceHolder', { - defaultMessage: 'Search field names', - }); - - const [isPopoverOpen, setPopoverOpen] = useState(false); - - const handleFilterButtonClicked = () => { - setPopoverOpen(!isPopoverOpen); - }; - - const buttonContent = ( - 0} - numFilters={0} - hasActiveFilters={fieldTypesValue.length > 0} - numActiveFilters={fieldTypesValue.length} - onClick={handleFilterButtonClicked} - > - - - ); - - return ( - - - - onSearchChange(event.currentTarget.value)} - placeholder={searchPlaceholder} - value={searchValue} - /> - - - - {}} isDisabled={!isPopoverOpen}> - - { - setPopoverOpen(false); - }} - button={buttonContent} - > - - {i18n.translate('presentationUtil.fieldSearch.filterByTypeLabel', { - defaultMessage: 'Filter by type', - })} - - ( - { - if (fieldTypesValue.includes(type)) { - onFieldTypesChange(fieldTypesValue.filter((f) => f !== type)); - } else { - onFieldTypesChange([...fieldTypesValue, type]); - } - }} - > - - - - - {type} - - - ))} - /> - - - - - ); -} diff --git a/src/plugins/presentation_util/public/components/field_picker/field_search.scss b/src/plugins/presentation_util/public/components/field_picker/field_type_filter.scss similarity index 100% rename from src/plugins/presentation_util/public/components/field_picker/field_search.scss rename to src/plugins/presentation_util/public/components/field_picker/field_type_filter.scss diff --git a/src/plugins/presentation_util/public/components/field_picker/field_type_filter.tsx b/src/plugins/presentation_util/public/components/field_picker/field_type_filter.tsx new file mode 100644 index 0000000000000..bb27137ce16c8 --- /dev/null +++ b/src/plugins/presentation_util/public/components/field_picker/field_type_filter.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiFilterGroup, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, + EuiContextMenuPanel, + EuiContextMenuItem, + EuiOutsideClickDetector, + EuiFilterButton, + EuiPopoverTitle, +} from '@elastic/eui'; +import { FieldIcon } from '@kbn/react-field'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import './field_type_filter.scss'; + +export interface Props { + onFieldTypesChange: (value: string[]) => void; + fieldTypesValue: string[]; + + availableFieldTypes: string[]; +} + +export function FieldTypeFilter({ + onFieldTypesChange, + fieldTypesValue, + availableFieldTypes, +}: Props) { + const [isPopoverOpen, setPopoverOpen] = useState(false); + + const handleFilterButtonClicked = () => { + setPopoverOpen(!isPopoverOpen); + }; + + const buttonContent = ( + 0} + numFilters={0} + hasActiveFilters={fieldTypesValue.length > 0} + numActiveFilters={fieldTypesValue.length} + onClick={handleFilterButtonClicked} + > + + + ); + + return ( + {}} isDisabled={!isPopoverOpen}> + + { + setPopoverOpen(false); + }} + button={buttonContent} + > + + {i18n.translate('presentationUtil.fieldSearch.filterByTypeLabel', { + defaultMessage: 'Filter by type', + })} + + ( + { + if (fieldTypesValue.includes(type)) { + onFieldTypesChange(fieldTypesValue.filter((f) => f !== type)); + } else { + onFieldTypesChange([...fieldTypesValue, type]); + } + }} + > + + + + + {type} + + + ))} + /> + + + + ); +} diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/index.ts b/src/plugins/presentation_util/public/components/solution_toolbar/index.ts deleted file mode 100644 index 84e313252d2e4..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/index.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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -/** @deprecated SolutionToolbar - use `Toolbar` from @kbn/shared-ux-button-toolbar" */ -export { SolutionToolbar } from './solution_toolbar'; -/** @deprecated QuickButtonGroup - use `IconButtonGroup` from `@kbn/shared-ux-button-toolbar` */ -/** @deprecated AddFromLibraryButton - use `AddFromLibraryButton` from `@kbn/shared-ux-button-toolbar` */ -/** @deprecated PrimaryButton and Button - use `Primary` from `@kbn/shared-ux-button-toolbar` */ -/** @deprecated PrimaryActionPopover - use `ToolbarPopover` from @kbn/shared-ux-button-toolber` */ -export * from './items'; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/add_from_library.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/items/add_from_library.tsx deleted file mode 100644 index 0550de1d069fa..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/add_from_library.tsx +++ /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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { ComponentStrings } from '../../../i18n/components'; -import { SolutionToolbarButton, Props as SolutionToolbarButtonProps } from './button'; - -const { SolutionToolbar: strings } = ComponentStrings; - -export type Props = Omit; - -export const AddFromLibraryButton = ({ onClick, ...rest }: Props) => ( - -); diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/button.scss b/src/plugins/presentation_util/public/components/solution_toolbar/items/button.scss deleted file mode 100644 index 4283813f1d0b7..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/button.scss +++ /dev/null @@ -1,12 +0,0 @@ -.solutionToolbarButton { - line-height: $euiButtonHeight; // Keeps alignment of text and chart icon - background-color: $euiColorEmptyShade; - - // Lighten the border color for all states - border-color: $euiBorderColor !important; // sass-lint:disable-line no-important - - &[class*='--text'] { - border-width: $euiBorderWidthThin; - border-style: solid; - } -} diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/button.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/items/button.tsx deleted file mode 100644 index a0a868875382d..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/button.tsx +++ /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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { EuiButton } from '@elastic/eui'; -import { EuiButtonPropsForButton } from '@elastic/eui/src/components/button/button'; - -import './button.scss'; - -export interface Props - extends Pick { - label: string; - primary?: boolean; - isDarkModeEnabled?: boolean; -} - -export const SolutionToolbarButton = ({ label, primary, className, ...rest }: Props) => ( - - {label} - -); diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/index.ts b/src/plugins/presentation_util/public/components/solution_toolbar/items/index.ts deleted file mode 100644 index cc6367bc3fcd5..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/index.ts +++ /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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { SolutionToolbarButton } from './button'; -export { SolutionToolbarPopover } from './popover'; -export { AddFromLibraryButton } from './add_from_library'; -export type { QuickButtonProps } from './quick_group'; -/** @deprecated use `IconButtonGroup` from `@kbn/shared-ux-button-toolbar` */ -export { QuickButtonGroup } from './quick_group'; -export { PrimaryActionButton } from './primary_button'; -export { PrimaryActionPopover } from './primary_popover'; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/popover.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/items/popover.tsx deleted file mode 100644 index 6f968d940b12d..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/popover.tsx +++ /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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useState } from 'react'; -import { EuiPopover, EuiPopoverProps } from '@elastic/eui'; - -import { SolutionToolbarButton, Props as ButtonProps } from './button'; - -type AllowedButtonProps = Omit; -type AllowedPopoverProps = Omit< - EuiPopoverProps, - 'button' | 'isOpen' | 'closePopover' | 'anchorPosition' ->; - -export type Props = AllowedButtonProps & - AllowedPopoverProps & { - children: (arg: { closePopover: () => void }) => React.ReactNode; - }; - -export const SolutionToolbarPopover = ({ - label, - iconType, - primary, - iconSide, - children, - ...popover -}: Props) => { - const [isOpen, setIsOpen] = useState(false); - - const onButtonClick = () => setIsOpen((status) => !status); - const closePopover = () => setIsOpen(false); - - const button = ( - - ); - - return ( - - {children({ closePopover })} - - ); -}; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.tsx deleted file mode 100644 index dcf16228ac63b..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/primary_button.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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; - -import { SolutionToolbarButton, Props as SolutionToolbarButtonProps } from './button'; - -import './primary_button.scss'; - -export interface Props extends Omit { - isDarkModeEnabled?: boolean; -} - -export const PrimaryActionButton = ({ isDarkModeEnabled, ...props }: Props) => ( - -); diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss b/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss deleted file mode 100644 index 9f70ae353405b..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.scss +++ /dev/null @@ -1,25 +0,0 @@ -.quickButtonGroup { - .euiButtonGroup__buttons { - border-radius: $euiBorderRadius; - - .quickButtonGroup__button { - background-color: $euiColorEmptyShade; - // sass-lint:disable-block no-important - border-width: $euiBorderWidthThin !important; - border-style: solid !important; - border-color: $euiBorderColor !important; - } - - .quickButtonGroup__button:first-of-type { - // sass-lint:disable-block no-important - border-top-left-radius: $euiBorderRadius !important; - border-bottom-left-radius: $euiBorderRadius !important; - } - - .quickButtonGroup__button:last-of-type { - // sass-lint:disable-block no-important - border-top-right-radius: $euiBorderRadius !important; - border-bottom-right-radius: $euiBorderRadius !important; - } - } -} diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx deleted file mode 100644 index 66b22eeb570db..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/items/quick_group.tsx +++ /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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { EuiButtonGroup, htmlIdGenerator, EuiButtonGroupOptionProps } from '@elastic/eui'; -import { ComponentStrings } from '../../../i18n/components'; - -const { QuickButtonGroup: strings } = ComponentStrings; - -import './quick_group.scss'; - -export interface QuickButtonProps extends Pick { - createType: string; - onClick: () => void; -} - -export interface Props { - buttons: QuickButtonProps[]; -} - -type Option = EuiButtonGroupOptionProps & Omit; - -export const QuickButtonGroup = ({ buttons }: Props) => { - const buttonGroupOptions: Option[] = buttons.map((button: QuickButtonProps, index) => { - const { createType: label, ...rest } = button; - const title = strings.getAriaButtonLabel(label); - - return { - ...rest, - 'aria-label': title, - className: `quickButtonGroup__button`, - id: `${htmlIdGenerator()()}${index}`, - label, - title, - }; - }); - - const onChangeIconsMulti = (optionId: string) => { - buttonGroupOptions.find((x) => x.id === optionId)?.onClick(); - }; - - return ( - - ); -}; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss b/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss deleted file mode 100644 index 30ef3f1d2c44f..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss +++ /dev/null @@ -1,16 +0,0 @@ -.solutionToolbar { - flex-grow: 0; - - // Temporary fix for two tone icons to make them monochrome - .solutionToolbar--dark { - .euiIcon path { - fill: $euiColorInk; - } - } - - .solutionToolbar--light { - .euiIcon path { - fill: $euiColorGhost; - } - } -} diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.stories.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.stories.tsx deleted file mode 100644 index e9daaf4ad7912..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.stories.tsx +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { Story } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; -import { EuiContextMenu } from '@elastic/eui'; - -import { SolutionToolbar } from './solution_toolbar'; -import { SolutionToolbarPopover } from './items'; - -import { AddFromLibraryButton, PrimaryActionButton, QuickButtonGroup } from './items'; - -const quickButtons = [ - { - createType: 'Text', - onClick: action('onTextClick'), - iconType: 'visText', - }, - { - createType: 'Control', - onClick: action('onControlClick'), - iconType: 'controlsHorizontal', - }, - { - createType: 'Link', - onClick: action('onLinkClick'), - iconType: 'link', - }, - { - createType: 'Image', - onClick: action('onImageClick'), - iconType: 'image', - }, - { - createType: 'Markup', - onClick: action('onMarkupClick'), - iconType: 'visVega', - }, -]; - -const primaryButtonConfigs = { - Generic: ( - - ), - Canvas: ( - - {() => ( - - )} - - ), - Dashboard: ( - - ), -}; - -const extraButtonConfigs = { - Generic: undefined, - Canvas: undefined, - Dashboard: [ - - {() => ( - - )} - , - ], -}; - -export default { - title: 'Solution Toolbar', - description: 'A universal toolbar for solutions maintained by the Presentation Team.', - component: SolutionToolbar, - argTypes: { - quickButtonCount: { - defaultValue: 2, - control: { - type: 'number', - min: 0, - max: 5, - step: 1, - }, - }, - showAddFromLibraryButton: { - defaultValue: true, - control: { - type: 'boolean', - }, - }, - solution: { - table: { - disable: true, - }, - }, - }, - // https://github.com/storybookjs/storybook/issues/11543#issuecomment-684130442 - parameters: { - docs: { - source: { - type: 'code', - }, - }, - }, -}; - -const Template: Story<{ - solution: 'Generic' | 'Canvas' | 'Dashboard'; - quickButtonCount: number; - showAddFromLibraryButton: boolean; -}> = ({ quickButtonCount, solution, showAddFromLibraryButton }) => { - const primaryActionButton = primaryButtonConfigs[solution]; - const extraButtons = extraButtonConfigs[solution]; - let quickButtonGroup; - let addFromLibraryButton; - - if (quickButtonCount > 0) { - quickButtonGroup = ; - } - - if (showAddFromLibraryButton) { - addFromLibraryButton = ; - } - - return ( - - {{ - primaryActionButton, - quickButtonGroup, - extraButtons, - addFromLibraryButton, - }} - - ); -}; - -export const Generic = Template.bind({}); -Generic.args = { - ...Template.args, - solution: 'Generic', -}; - -export const Canvas = Template.bind({}); -Canvas.args = { - ...Template.args, - solution: 'Canvas', -}; - -export const Dashboard = Template.bind({}); -Dashboard.args = { - ...Template.args, - solution: 'Dashboard', -}; diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.tsx b/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.tsx deleted file mode 100644 index 219c582f26a3a..0000000000000 --- a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.tsx +++ /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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { ReactElement } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -import { - QuickButtonGroup, - PrimaryActionButton, - SolutionToolbarButton, - PrimaryActionPopover, - SolutionToolbarPopover, -} from './items'; - -import './solution_toolbar.scss'; - -interface NamedSlots { - primaryActionButton: ReactElement; - quickButtonGroup?: ReactElement; - extraButtons?: Array< - ReactElement | undefined - >; -} - -export interface Props { - isDarkModeEnabled?: boolean; - children: NamedSlots; -} - -export const SolutionToolbar = ({ isDarkModeEnabled, children }: Props) => { - const { primaryActionButton, quickButtonGroup, extraButtons = [] } = children; - - const extra = extraButtons.map((button, index) => - button ? ( - - {button} - - ) : null - ); - - return ( - - {primaryActionButton} - - - {quickButtonGroup ? {quickButtonGroup} : null} - {extra} - - - - ); -}; diff --git a/src/plugins/presentation_util/public/i18n/components.ts b/src/plugins/presentation_util/public/i18n/components.ts deleted file mode 100644 index ab0e6d1bdbda0..0000000000000 --- a/src/plugins/presentation_util/public/i18n/components.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -export const ComponentStrings = { - SolutionToolbar: { - getEditorMenuButtonLabel: () => - i18n.translate('presentationUtil.solutionToolbar.editorMenuButtonLabel', { - defaultMessage: 'All editors', - }), - getLibraryButtonLabel: () => - i18n.translate('presentationUtil.solutionToolbar.libraryButtonLabel', { - defaultMessage: 'Add from library', - }), - }, - QuickButtonGroup: { - getAriaButtonLabel: (createType: string) => - i18n.translate('presentationUtil.solutionToolbar.quickButton.ariaButtonLabel', { - defaultMessage: `Create new {createType}`, - values: { - createType, - }, - }), - getLegend: () => - i18n.translate('presentationUtil.solutionToolbar.quickButton.legendLabel', { - defaultMessage: 'Quick create', - }), - }, -}; diff --git a/src/plugins/presentation_util/public/index.ts b/src/plugins/presentation_util/public/index.ts index 24bcc6af474de..51f8a2c902541 100644 --- a/src/plugins/presentation_util/public/index.ts +++ b/src/plugins/presentation_util/public/index.ts @@ -54,25 +54,6 @@ export type { OnExpressionInputEditorDidMount, } from './components/types'; -/** @deprecated QuickButtonProps - use `IconButtonGroupProps` from `@kbn/shared-ux-button-toolbar` */ -export type { QuickButtonProps } from './components/solution_toolbar'; - -export { - /** @deprecated AddFromLibraryButton - use `AddFromLibraryButton` from `@kbn/shared-ux-button-toolbar` */ - AddFromLibraryButton, - /** @deprecated PrimaryActionButton - use `PrimaryButton` from `@kbn/shared-ux-button-toolbar` */ - PrimaryActionButton, - /** @deprecated SolutionToolbarPopover - use `ToolbarPopover` from `@kbn/shared-ux-button-toolbar` */ - PrimaryActionPopover, - /** @deprecated QuickButtonGroup - use `IconButtonGroup` from `@kbn/shared-ux-button-toolbar` */ - QuickButtonGroup, - SolutionToolbar, - /** @deprecated SolutionToolbarButton - use `PrimaryButton` from `@kbn/shared-ux-button-toolbar` */ - SolutionToolbarButton, - /** @deprecated SolutionToolbarPopover - use `ToolbarPopover` from `@kbn/shared-ux-button-toolbar` */ - SolutionToolbarPopover, -} from './components/solution_toolbar'; - /** * Register a set of Expression Functions with the Presentation Utility ExpressionInput. This allows * the Monaco Editor to understand the functions and their arguments. diff --git a/test/functional/page_objects/dashboard_page_controls.ts b/test/functional/page_objects/dashboard_page_controls.ts index c3160e650c2a8..ff4ac5b67f804 100644 --- a/test/functional/page_objects/dashboard_page_controls.ts +++ b/test/functional/page_objects/dashboard_page_controls.ts @@ -576,7 +576,7 @@ export class DashboardPageControls extends FtrService { public async controlsEditorSetfield( fieldName: string, expectedType?: string, - shouldSearch: boolean = false + shouldSearch: boolean = true ) { this.log.debug(`Setting control field to ${fieldName}`); if (shouldSearch) { diff --git a/test/harden/lodash_template.js b/test/harden/lodash_template.js index b04f8ad66275a..49cf7351972e8 100644 --- a/test/harden/lodash_template.js +++ b/test/harden/lodash_template.js @@ -11,6 +11,7 @@ const _ = require('lodash'); // eslint-disable-next-line no-restricted-modules const template = require('lodash/template'); const fp = require('lodash/fp'); +// eslint-disable-next-line no-restricted-modules const fpTemplate = require('lodash/fp/template'); const test = require('tape'); diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx index aaf5b8e523dca..9307d9eced93b 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx @@ -233,7 +233,7 @@ export const SpikeAnalysisTable: FC = ({ content={i18n.translate( 'xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.impactLabelColumnTooltip', { - defaultMessage: 'The level of impact of the field on the message rate difference', + defaultMessage: 'The level of impact of the field on the message rate difference.', } )} > diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx index 954770950e036..363aff283c4cc 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx @@ -328,7 +328,7 @@ export const SpikeAnalysisGroupsTable: FC = ({ 'xpack.aiops.explainLogRateSpikes.spikeAnalysisTableGroups.logRateColumnTooltip', { defaultMessage: - 'A visual representation of the impact of the group on the message rate difference', + 'A visual representation of the impact of the group on the message rate difference.', } )} > @@ -377,7 +377,7 @@ export const SpikeAnalysisGroupsTable: FC = ({ 'xpack.aiops.explainLogRateSpikes.spikeAnalysisTableGroups.pValueColumnTooltip', { defaultMessage: - 'The significance of changes in the frequency of values; lower values indicate greater change', + 'The significance of changes in the frequency of values; lower values indicate greater change.', } )} > diff --git a/x-pack/plugins/alerting/server/lib/index.ts b/x-pack/plugins/alerting/server/lib/index.ts index 8f8dccadaaa77..0dd0008964e24 100644 --- a/x-pack/plugins/alerting/server/lib/index.ts +++ b/x-pack/plugins/alerting/server/lib/index.ts @@ -27,7 +27,7 @@ export { } from './rule_execution_status'; export { lastRunFromState, lastRunFromError, lastRunToRaw } from './last_run_status'; export { - updateMonitoring, + resetMonitoringLastRun, getDefaultMonitoring, convertMonitoringFromRawAndVerify, } from './monitoring'; diff --git a/x-pack/plugins/alerting/server/lib/monitoring.test.ts b/x-pack/plugins/alerting/server/lib/monitoring.test.ts index 492e205a99508..5d417c2735681 100644 --- a/x-pack/plugins/alerting/server/lib/monitoring.test.ts +++ b/x-pack/plugins/alerting/server/lib/monitoring.test.ts @@ -5,47 +5,56 @@ * 2.0. */ +import { RuleMonitoring, RuleMonitoringHistory } from '../types'; import { getExecutionDurationPercentiles, updateMonitoring, convertMonitoringFromRawAndVerify, + resetMonitoringLastRun, } from './monitoring'; -import { RuleMonitoring } from '../types'; -const mockHistory = [ +const mockHistory: RuleMonitoringHistory[] = [ { + timestamp: 1655427600000, success: true, duration: 100, }, { + timestamp: 1655427900000, success: true, duration: 200, }, { + timestamp: 1655428200000, success: false, duration: 300, }, { + timestamp: 1655428500000, success: false, duration: 100, }, { + timestamp: 1655428800000, success: false, }, { + timestamp: 1655429100000, success: true, }, { + timestamp: 1655429400000, success: true, duration: 400, }, { + timestamp: 1655429700000, success: true, duration: 500, }, ]; -const mockRuleMonitoring = { +const mockRuleMonitoring: RuleMonitoring = { run: { history: mockHistory, calculated_metrics: { @@ -58,7 +67,7 @@ const mockRuleMonitoring = { }, }, }, -} as RuleMonitoring; +}; describe('getExecutionDurationPercentiles', () => { it('Calculates the percentile given partly undefined durations', () => { @@ -70,23 +79,57 @@ describe('getExecutionDurationPercentiles', () => { it('Returns empty object when given all undefined durations', () => { // remove all duration fields - const nullDurationHistory = mockHistory.map((history) => ({ + const nullDurationHistory: RuleMonitoringHistory[] = mockHistory.map((history) => ({ + timestamp: history.timestamp, success: history.success, })); - const newMockRuleMonitoring = { + const newMockRuleMonitoring: RuleMonitoring = { ...mockRuleMonitoring, run: { ...mockRuleMonitoring.run, history: nullDurationHistory, }, - } as RuleMonitoring; + }; const percentiles = getExecutionDurationPercentiles(newMockRuleMonitoring.run.history); expect(Object.keys(percentiles).length).toEqual(0); }); }); +describe('resetMonitoringLastRun', () => { + it('resets last run metrics to the initial default value', () => { + const result = resetMonitoringLastRun(mockRuleMonitoring); + expect(result.run.last_run.metrics).toEqual({ + duration: 0, + total_search_duration_ms: null, + total_indexing_duration_ms: null, + total_alerts_detected: null, + total_alerts_created: null, + gap_duration_s: null, + }); + }); + + it('preserves last run timestamp', () => { + const expectedTimestamp = mockRuleMonitoring.run.last_run.timestamp; + const result = resetMonitoringLastRun(mockRuleMonitoring); + expect(result.run.last_run.timestamp).toEqual(expectedTimestamp); + }); + + it('preserves other monitoring properties', () => { + const { run: originalRun, ...originalRestOfMonitoringObject } = mockRuleMonitoring; + const { last_run: originalLastRun, ...originalRestOfRunObject } = originalRun; + + const result = resetMonitoringLastRun(mockRuleMonitoring); + + const { run: actualRun, ...actualRestOfMonitoringObject } = result; + const { last_run: actualLastRun, ...actualRestOfRunObject } = actualRun; + + expect(actualRestOfMonitoringObject).toEqual(originalRestOfMonitoringObject); + expect(actualRestOfRunObject).toEqual(originalRestOfRunObject); + }); +}); + describe('updateMonitoring', () => { it('can update monitoring', () => { const result = updateMonitoring({ diff --git a/x-pack/plugins/alerting/server/lib/monitoring.ts b/x-pack/plugins/alerting/server/lib/monitoring.ts index 93da6e2283152..9224600eeffc7 100644 --- a/x-pack/plugins/alerting/server/lib/monitoring.ts +++ b/x-pack/plugins/alerting/server/lib/monitoring.ts @@ -6,9 +6,15 @@ */ import { Logger } from '@kbn/core/server'; import stats from 'stats-lite'; -import { RuleMonitoring, RawRuleMonitoring, RuleMonitoringHistory } from '../types'; +import { + RuleMonitoring, + RawRuleMonitoring, + RuleMonitoringHistory, + RuleMonitoringLastRunMetrics, +} from '../types'; -export const INITIAL_METRICS = { +const INITIAL_LAST_RUN_METRICS: RuleMonitoringLastRunMetrics = { + duration: 0, total_search_duration_ms: null, total_indexing_duration_ms: null, total_alerts_detected: null, @@ -25,29 +31,26 @@ export const getDefaultMonitoring = (timestamp: string): RawRuleMonitoring => { }, last_run: { timestamp, - metrics: INITIAL_METRICS, + metrics: INITIAL_LAST_RUN_METRICS, }, }, }; }; -export const getExecutionDurationPercentiles = (history: RuleMonitoringHistory[]) => { - const durationSamples = history.reduce((duration, historyItem) => { - if (typeof historyItem.duration === 'number') { - return [...duration, historyItem.duration]; - } - return duration; - }, []); +export const resetMonitoringLastRun = (monitoring: RuleMonitoring): RawRuleMonitoring => { + const { run, ...restMonitoring } = monitoring; + const { last_run: lastRun, ...restRun } = run; - if (durationSamples.length) { - return { - p50: stats.percentile(durationSamples as number[], 0.5), - p95: stats.percentile(durationSamples as number[], 0.95), - p99: stats.percentile(durationSamples as number[], 0.99), - }; - } - - return {}; + return { + ...restMonitoring, + run: { + ...restRun, + last_run: { + timestamp: lastRun.timestamp, + metrics: INITIAL_LAST_RUN_METRICS, + }, + }, + }; }; // Immutably updates the monitoring object with timestamp and duration. @@ -60,13 +63,15 @@ export const updateMonitoring = ({ monitoring: RuleMonitoring; timestamp: string; duration?: number; -}) => { - const { run } = monitoring; - const { last_run: lastRun, ...rest } = run; - const { metrics = INITIAL_METRICS } = lastRun; +}): RawRuleMonitoring => { + const { run, ...restMonitoring } = monitoring; + const { last_run: lastRun, ...restRun } = run; + const { metrics = INITIAL_LAST_RUN_METRICS } = lastRun; return { + ...restMonitoring, run: { + ...restRun, last_run: { timestamp, metrics: { @@ -74,7 +79,6 @@ export const updateMonitoring = ({ duration, }, }, - ...rest, }, }; }; @@ -102,3 +106,22 @@ export const convertMonitoringFromRawAndVerify = ( duration: monitoring.run.last_run.metrics.duration, }); }; + +export const getExecutionDurationPercentiles = (history: RuleMonitoringHistory[]) => { + const durationSamples = history.reduce((duration, historyItem) => { + if (typeof historyItem.duration === 'number') { + return [...duration, historyItem.duration]; + } + return duration; + }, []); + + if (durationSamples.length) { + return { + p50: stats.percentile(durationSamples as number[], 0.5), + p95: stats.percentile(durationSamples as number[], 0.95), + p99: stats.percentile(durationSamples as number[], 0.99), + }; + } + + return {}; +}; diff --git a/x-pack/plugins/alerting/server/rules_client/methods/enable.ts b/x-pack/plugins/alerting/server/rules_client/methods/enable.ts index 5b26061120b0a..1aee25fa5adbc 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/enable.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/enable.ts @@ -6,7 +6,7 @@ */ import { RawRule, IntervalSchedule } from '../../types'; -import { updateMonitoring, getNextRun } from '../../lib'; +import { resetMonitoringLastRun, getNextRun } from '../../lib'; import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization'; import { retryIfConflicts } from '../../lib/retry_if_conflicts'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; @@ -84,11 +84,7 @@ async function enableWithOCC(context: RulesClientContext, { id }: { id: string } ...attributes, ...(!existingApiKey && (await createNewAPIKeySet(context, { attributes, username }))), ...(attributes.monitoring && { - monitoring: updateMonitoring({ - monitoring: attributes.monitoring, - timestamp: now.toISOString(), - duration: 0, - }), + monitoring: resetMonitoringLastRun(attributes.monitoring), }), nextRun: getNextRun({ interval: schedule.interval }), enabled: true, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts index 84226a318f9c3..8d5d681845f8a 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts @@ -439,6 +439,7 @@ describe('create()', () => { "history": Array [], "last_run": Object { "metrics": Object { + "duration": 0, "gap_duration_s": null, "total_alerts_created": null, "total_alerts_detected": null, @@ -658,6 +659,7 @@ describe('create()', () => { "history": Array [], "last_run": Object { "metrics": Object { + "duration": 0, "gap_duration_s": null, "total_alerts_created": null, "total_alerts_detected": null, @@ -2097,6 +2099,7 @@ describe('create()', () => { last_run: { timestamp: '2019-02-12T21:01:22.479Z', metrics: { + duration: 0, gap_duration_s: null, total_alerts_created: null, total_alerts_detected: null, diff --git a/x-pack/plugins/alerting/server/task_runner/fixtures.ts b/x-pack/plugins/alerting/server/task_runner/fixtures.ts index 920afcfbe3035..8558cd6cbd70f 100644 --- a/x-pack/plugins/alerting/server/task_runner/fixtures.ts +++ b/x-pack/plugins/alerting/server/task_runner/fixtures.ts @@ -101,6 +101,7 @@ export const generateSavedObjectParams = ({ last_run: { timestamp: '1970-01-01T00:00:00.000Z', metrics: { + duration: 0, gap_duration_s: null, total_alerts_created: null, total_alerts_detected: null, @@ -281,6 +282,7 @@ export const generateRunnerResult = ({ history: history.map((success) => ({ success, timestamp: 0 })), last_run: { metrics: { + duration: 0, gap_duration_s: null, total_alerts_created: null, total_alerts_detected: null, diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 84ee0f101d8b8..abe4b2b6c46a7 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -246,6 +246,7 @@ describe('Task Runner Cancel', () => { history: [], last_run: { metrics: { + duration: 0, gap_duration_s: null, total_alerts_created: null, total_alerts_detected: null, diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/error_details.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/error_details.cy.ts index 2c837abd2bc4d..8714fe8f07873 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/error_details.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/error_details.cy.ts @@ -48,7 +48,7 @@ describe('Error details', () => { }); describe('when error has no occurrences', () => { - it('shows an empty message', () => { + it('shows zero occurrences', () => { cy.visitKibana( url.format({ pathname: @@ -60,7 +60,7 @@ describe('Error details', () => { }, }) ); - cy.contains('No data to display'); + cy.contains('0 occ'); }); }); diff --git a/x-pack/plugins/apm/public/components/app/service_map/disabled_prompt.tsx b/x-pack/plugins/apm/public/components/app/service_map/disabled_prompt.tsx new file mode 100644 index 0000000000000..77f8a0ea505c5 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/service_map/disabled_prompt.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +export function DisabledPrompt() { + return ( + + {i18n.translate('xpack.apm.serviceMap.disabledTitle', { + defaultMessage: 'Service map is disabled', + })} +

+ } + body={ +

+ {i18n.translate('xpack.apm.serviceMap.disabledDescription', { + defaultMessage: + 'The service map has been disabled. It can be enabled via `xpack.apm.serviceMapEnabled`', + })} +

+ } + /> + ); +} diff --git a/x-pack/plugins/apm/public/components/app/service_map/index.tsx b/x-pack/plugins/apm/public/components/app/service_map/index.tsx index bc75102fa7d67..2b3d8c8eaf15c 100644 --- a/x-pack/plugins/apm/public/components/app/service_map/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_map/index.tsx @@ -12,6 +12,7 @@ import { EuiPanel, } from '@elastic/eui'; import React, { ReactNode } from 'react'; +import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { isActivePlatinumLicense } from '../../../../common/license_check'; import { invalidLicenseMessage, @@ -34,6 +35,7 @@ import { useServiceName } from '../../../hooks/use_service_name'; import { useApmParams, useAnyOfApmParams } from '../../../hooks/use_apm_params'; import { Environment } from '../../../../common/environment_rt'; import { useTimeRange } from '../../../hooks/use_time_range'; +import { DisabledPrompt } from './disabled_prompt'; function PromptContainer({ children }: { children: ReactNode }) { return ( @@ -114,8 +116,8 @@ export function ServiceMap({ }) { const theme = useTheme(); const license = useLicenseContext(); - const serviceName = useServiceName(); + const { config } = useApmPluginContext(); const { data = { elements: [] }, @@ -124,7 +126,11 @@ export function ServiceMap({ } = useFetcher( (callApmApi) => { // When we don't have a license or a valid license, don't make the request. - if (!license || !isActivePlatinumLicense(license)) { + if ( + !license || + !isActivePlatinumLicense(license) || + !config.serviceMapEnabled + ) { return; } @@ -142,7 +148,16 @@ export function ServiceMap({ }, }); }, - [license, serviceName, environment, start, end, serviceGroupId, kuery] + [ + license, + serviceName, + environment, + start, + end, + serviceGroupId, + kuery, + config.serviceMapEnabled, + ] ); const { ref, height } = useRefDimensions(); @@ -163,6 +178,14 @@ export function ServiceMap({ ); } + if (!config.serviceMapEnabled) { + return ( + + + + ); + } + if (status === FETCH_STATUS.SUCCESS && data.elements.length === 0) { return ( diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx index ed84d13641260..18d911a7c2342 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx @@ -14,7 +14,7 @@ import { import { i18n } from '@kbn/i18n'; import { EmbeddableFactoryDefinition } from '@kbn/embeddable-plugin/public'; import { BaseVisType, VisTypeAlias } from '@kbn/visualizations-plugin/public'; -import { SolutionToolbarPopover } from '@kbn/presentation-util-plugin/public'; +import { ToolbarPopover } from '@kbn/shared-ux-button-toolbar'; const strings = { getEditorMenuButtonLabel: () => @@ -145,11 +145,9 @@ export const EditorMenu: FC = ({ ]; return ( - @@ -165,6 +163,6 @@ export const EditorMenu: FC = ({ data-test-subj="canvasEditorContextMenu" /> )} - + ); }; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx index 784c040ee6174..8c8edbf24b1c1 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx @@ -9,8 +9,8 @@ import { sortBy } from 'lodash'; import React, { FunctionComponent, useState } from 'react'; import PropTypes from 'prop-types'; import { EuiContextMenu, EuiIcon, EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; +import { ToolbarPopover } from '@kbn/shared-ux-button-toolbar'; import { i18n } from '@kbn/i18n'; -import { PrimaryActionPopover } from '@kbn/presentation-util-plugin/public'; import { getId } from '../../../lib/get_id'; import { CONTEXT_MENU_TOP_BORDER_CLASSNAME } from '../../../../common/lib'; import { ElementSpec } from '../../../../types'; @@ -203,7 +203,8 @@ export const ElementMenu: FunctionComponent = ({ elements, addElement }) return ( <> - = ({ elements, addElement }) panels={flattenPanelTree(getPanelTree(closePopover))} /> )} - + {isAssetModalVisible ? : null} {isSavedElementsModalVisible ? : null} diff --git a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx index 5bba9ce3895f5..ddac56a5a7731 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx @@ -12,11 +12,8 @@ import { Shortcuts } from 'react-shortcuts'; import { EuiFlexItem, EuiFlexGroup, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { - AddFromLibraryButton, - QuickButtonGroup, - SolutionToolbar, -} from '@kbn/presentation-util-plugin/public'; +import { AddFromLibraryButton, IconButtonGroup, Toolbar } from '@kbn/shared-ux-button-toolbar'; + import { getElementStrings } from '../../../i18n'; import { CommitFn, ElementSpec } from '../../../types'; import { ToolTipShortcut } from '../tool_tip_shortcut'; @@ -31,6 +28,10 @@ import { LabsControl } from './labs_control'; import { EditorMenu } from './editor_menu'; const strings = { + getQuickCreateButtonGroupLegend: () => + i18n.translate('xpack.canvas.workpadHeader.quickCreateButtonGroupLegend', { + defaultMessage: 'Shortcuts to popular element types', + }), getFullScreenButtonAriaLabel: () => i18n.translate('xpack.canvas.workpadHeader.fullscreenButtonAriaLabel', { defaultMessage: 'View fullscreen', @@ -142,34 +143,35 @@ export const WorkpadHeader: FC = ({ const quickButtons = [ { iconType: 'visText', - createType: elementStrings.markdown.displayName, - onClick: createElement('markdown'), + label: elementStrings.markdown.displayName, + onClick: () => createElement('markdown'), }, { iconType: 'node', - createType: elementStrings.shape.displayName, - onClick: createElement('shape'), + label: elementStrings.shape.displayName, + onClick: () => createElement('shape'), }, { iconType: 'image', - createType: elementStrings.image.displayName, - onClick: createElement('image'), + label: elementStrings.image.displayName, + onClick: () => createElement('image'), }, ]; return ( <> - + {isWriteable && ( - + {{ - primaryActionButton: , - quickButtonGroup: , + primaryButton: , + iconButtonGroup: ( + + ), extraButtons: [ = ({ , ], }} - + )} diff --git a/x-pack/plugins/canvas/tsconfig.json b/x-pack/plugins/canvas/tsconfig.json index ae50b56a27bed..ef10a58a1e65b 100644 --- a/x-pack/plugins/canvas/tsconfig.json +++ b/x-pack/plugins/canvas/tsconfig.json @@ -78,6 +78,7 @@ "@kbn/flot-charts", "@kbn/shared-ux-router", "@kbn/babel-register", + "@kbn/shared-ux-button-toolbar", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/cloud_defend/public/components/control_general_view/translations.ts b/x-pack/plugins/cloud_defend/public/components/control_general_view/translations.ts index 26c77aa6aa74b..b886bd1c4d68a 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_general_view/translations.ts +++ b/x-pack/plugins/cloud_defend/public/components/control_general_view/translations.ts @@ -21,7 +21,7 @@ export const selectors = i18n.translate('xpack.cloudDefend.controlSelectors', { }); export const selectorsHelp = i18n.translate('xpack.cloudDefend.controlSelectorsHelp', { - defaultMessage: 'Create selectors to match on activities that should be blocked or alerted.', + defaultMessage: 'Create selectors to match on operations that should be blocked or alerted.', }); export const responses = i18n.translate('xpack.cloudDefend.controlResponses', { @@ -99,6 +99,22 @@ export const errorValueLengthExceeded = i18n.translate( } ); +export const getConditionHelpLabel = (prop: string) => { + switch (prop) { + case ControlSelectorCondition.ignoreVolumeMounts: + return i18n.translate('xpack.cloudDefend.ignoreVolumeMountsHelp', { + defaultMessage: 'Ignore operations on all volume mounts.', + }); + case ControlSelectorCondition.ignoreVolumeFiles: + return i18n.translate('xpack.cloudDefend.ignoreVolumeFilesHelp', { + defaultMessage: + 'Ignore operations on file mounts only. e.g mounted files, configMaps, secrets etc...', + }); + default: + return ''; + } +}; + export const getConditionLabel = (prop: string) => { switch (prop) { case ControlSelectorCondition.operation: @@ -117,6 +133,14 @@ export const getConditionLabel = (prop: string) => { return i18n.translate('xpack.cloudDefend.targetFilePath', { defaultMessage: 'Target file path', }); + case ControlSelectorCondition.ignoreVolumeFiles: + return i18n.translate('xpack.cloudDefend.ignoreVolumeFiles', { + defaultMessage: 'Ignore volume files', + }); + case ControlSelectorCondition.ignoreVolumeMounts: + return i18n.translate('xpack.cloudDefend.ignoreVolumeMounts', { + defaultMessage: 'Ignore volume mounts', + }); case ControlSelectorCondition.orchestratorClusterId: return i18n.translate('xpack.cloudDefend.orchestratorClusterId', { defaultMessage: 'Orchestrator cluster ID', @@ -141,5 +165,7 @@ export const getConditionLabel = (prop: string) => { return i18n.translate('xpack.cloudDefend.orchestratorResourceType', { defaultMessage: 'Orchestrator resource type', }); + default: + return ''; } }; diff --git a/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.test.tsx b/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.test.tsx index 35f1a418725a0..77273cc1b2ba1 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.test.tsx +++ b/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.test.tsx @@ -118,6 +118,21 @@ describe('', () => { expect(updatedOptions[0]).not.toHaveTextContent('containerImageName'); }); + it('allows the user add boolean type conditions', async () => { + const { getByTestId, rerender } = render(); + const addConditionBtn = getByTestId('cloud-defend-btnaddselectorcondition'); + + userEvent.click(addConditionBtn); + + const addIgnoreVolumeMounts = getByTestId('cloud-defend-addmenu-ignoreVolumeMounts'); + + await waitFor(() => userEvent.click(addIgnoreVolumeMounts)); + + const updatedSelector: ControlSelector = { ...onChange.mock.calls[0][0] }; + rerender(); + expect(updatedSelector.ignoreVolumeMounts).toBeTruthy(); + }); + it('shows an error if no conditions are added', async () => { const { getByText, getByTestId, rerender } = render(); diff --git a/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx b/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx index 1bcedbe13cc4a..bc42466c63329 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx +++ b/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx @@ -19,6 +19,7 @@ import { EuiSpacer, EuiFlexGroup, EuiFlexItem, + EuiText, } from '@elastic/eui'; import { useStyles } from './styles'; import { @@ -26,6 +27,7 @@ import { ControlFormErrorMap, ControlSelectorCondition, ControlSelectorConditionUIOptionsMap, + ControlSelectorBooleanConditions, ControlSelector, } from '../../types'; import * as i18n from '../control_general_view/translations'; @@ -36,6 +38,104 @@ import { MAX_FILE_PATH_VALUE_LENGTH_BYTES, } from '../../common/constants'; +interface ConditionProps { + label: string; + prop: string; + onRemoveCondition(prop: string): void; +} + +interface StringArrayConditionProps extends ConditionProps { + selector: ControlSelector; + errorMap: ControlFormErrorMap; + onAddValueToCondition(prop: string, value: string): void; + onChangeStringArrayCondition(prop: string, value: string[]): void; +} + +const BooleanCondition = ({ label, prop, onRemoveCondition }: ConditionProps) => { + return ( + + + + +

+ {i18n.getConditionHelpLabel(prop)} +

+
+
+ + onRemoveCondition(prop)} + aria-label="Remove condition" + data-test-subj={'cloud-defend-btnremovecondition-' + prop} + /> + +
+
+ ); +}; + +const StringArrayCondition = ({ + label, + prop, + selector, + errorMap, + onRemoveCondition, + onAddValueToCondition, + onChangeStringArrayCondition, +}: StringArrayConditionProps) => { + const values = selector[prop as keyof ControlSelector] as string[]; + const selectedOptions = + values?.map((option) => { + return { label: option, value: option }; + }) || []; + + const restrictedValues = ControlSelectorConditionUIOptionsMap[prop]?.values; + + return ( + + + + onAddValueToCondition(prop, searchValue) + : undefined + } + selectedOptions={selectedOptions} + options={ + restrictedValues + ? restrictedValues.map((value: string) => ({ label: value, value })) + : selectedOptions + } + onChange={(options) => + onChangeStringArrayCondition(prop, options.map((option) => option.value) as string[]) + } + isClearable + data-test-subj={'cloud-defend-selectorcondition-' + prop} + /> + + + onRemoveCondition(prop)} + aria-label="Remove condition" + data-test-subj={'cloud-defend-btnremovecondition-' + prop} + /> + + + + ); +}; + +/** main component */ export const ControlGeneralViewSelector = ({ selector, selectors, @@ -121,7 +221,7 @@ export const ControlGeneralViewSelector = ({ [errorMap, index, conditionsAdded, onChange, selector, selectors] ); - const onChangeCondition = useCallback( + const onChangeStringArrayCondition = useCallback( (prop: string, values: string[]) => { const updatedSelector = { ...selector, [prop]: values }; const errors = []; @@ -156,12 +256,25 @@ export const ControlGeneralViewSelector = ({ [errorMap, index, conditionsAdded, onChange, selector] ); + const onChangeBooleanCondition = useCallback( + (prop: string, value: boolean) => { + const updatedSelector = { ...selector, [prop]: value }; + + onChange(updatedSelector, index); + }, + [index, onChange, selector] + ); + const onAddCondition = useCallback( (prop: string) => { - onChangeCondition(prop, []); + if (prop in ControlSelectorBooleanConditions) { + onChangeBooleanCondition(prop, true); + } else { + onChangeStringArrayCondition(prop, []); + } closeAddCondition(); }, - [closeAddCondition, onChangeCondition] + [closeAddCondition, onChangeBooleanCondition, onChangeStringArrayCondition] ); const onRemoveCondition = useCallback( @@ -185,10 +298,10 @@ export const ControlGeneralViewSelector = ({ const values = selector[prop as keyof ControlSelector] as string[]; if (values && values.indexOf(value) === -1) { - onChangeCondition(prop, [...values, value]); + onChangeStringArrayCondition(prop, [...values, value]); } }, - [onChangeCondition, selector] + [onChangeStringArrayCondition, selector] ); const errors = useMemo(() => { @@ -270,56 +383,31 @@ export const ControlGeneralViewSelector = ({ {Object.keys(selector).map((prop: string) => { if (['name', 'hasErrors'].indexOf(prop) === -1) { - const values = selector[prop as keyof ControlSelector] as string[]; - const selectedOptions = - values?.map((option) => { - return { label: option, value: option }; - }) || []; - const label = i18n.getConditionLabel(prop); - const restrictedValues = ControlSelectorConditionUIOptionsMap[prop]?.values; - return ( - - - - onAddValueToCondition(prop, searchValue) - : undefined - } - selectedOptions={selectedOptions} - options={ - restrictedValues - ? restrictedValues.map((value: string) => ({ label: value, value })) - : selectedOptions - } - onChange={(options) => - onChangeCondition(prop, options.map((option) => option.value) as string[]) - } - isClearable - data-test-subj={'cloud-defend-selectorcondition-' + prop} - /> - - - onRemoveCondition(prop)} - aria-label="Remove condition" - data-test-subj={'cloud-defend-btnremovecondition-' + prop} - /> - - - - ); + if (prop in ControlSelectorBooleanConditions) { + return ( + + ); + } else { + return ( + + ); + } } })} @@ -345,7 +433,11 @@ export const ControlGeneralViewSelector = ({ size="s" items={remainingProps.map((prop) => { return ( - onAddCondition(prop)}> + onAddCondition(prop)} + > {i18n.getConditionLabel(prop)} ); diff --git a/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/policy_schema.json b/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/policy_schema.json new file mode 100644 index 0000000000000..e3c5a2675dcad --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/policy_schema.json @@ -0,0 +1,190 @@ +{ + "$id": "https://elastic.co/cloud-defend/policy-schema.json", + "type": "object", + "required": ["selectors", "responses"], + "additionalProperties": false, + "properties": { + "selectors": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/selector" + } + }, + "responses": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/response" + } + } + }, + "$defs": { + "selector": { + "type": "object", + "required": ["name"], + "additionalProperties": false, + "anyOf": [ + { + "required": ["operation"] + }, + { + "required": ["containerImageName"] + }, + { + "required": ["containerImageTag"] + }, + { + "required": ["targetFilePath"] + }, + { + "required": ["orchestratorClusterId"] + }, + { + "required": ["orchestratorClusterName"] + }, + { + "required": ["orchestratorNamespace"] + }, + { + "required": ["orchestratorResourceLabel"] + }, + { + "required": ["orchestratorResourceName"] + }, + { + "required": ["orchestratorType"] + }, + { + "required": ["ignoreVolumeMounts"] + }, + { + "required": ["ignoreVolumeFiles"] + } + ], + "properties": { + "name": { + "type": "string" + }, + "operation": { + "type": "array", + "minItems": 1, + "items": { + "enum": [ + "createExecutable", + "modifyExecutable", + "createFile", + "modifyFile", + "deleteFile" + ] + } + }, + "containerImageName": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "containerImageTag": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "targetFilePath": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "orchestratorClusterId": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "orchestratorClusterName": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "orchestratorNamespace": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "orchestratorResourceLabel": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "orchestratorResourceName": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "orchestratorType": { + "type": "array", + "minItems": 1, + "items": { + "enum": ["kubernetes"] + } + }, + "ignoreVolumeMounts": { + "type": "boolean", + "description": "Ignore all volume mounts. e.g directories, files, configMaps, secrets etc...\nNote: should not be used with ignoreVolumeFiles" + }, + "ignoreVolumeFiles": { + "type": "boolean", + "description": "Ignore file mounts. e.g files, configMaps, secrets\nNote: should not be used with ignoreVolumeMounts" + } + }, + "dependencies": { + "ignoreVolumeMounts": { + "not": { + "required": ["ignoreVolumeFiles"] + } + } + } + }, + "response": { + "type": "object", + "required": ["match", "actions"], + "additionalProperties": false, + "properties": { + "match": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + } + }, + "actions": { + "type": "array", + "minItems": 1, + "items": { + "enum": ["alert", "block"] + } + } + } + } + } +} diff --git a/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/use_config_model.ts b/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/use_config_model.ts index 36d9628214fbe..359639f2a56cf 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/use_config_model.ts +++ b/x-pack/plugins/cloud_defend/public/components/control_yaml_view/hooks/use_config_model.ts @@ -8,7 +8,13 @@ import { useMemo } from 'react'; import yaml from 'js-yaml'; import { setDiagnosticsOptions } from 'monaco-yaml'; import { monaco } from '@kbn/monaco'; -import { MAX_CONDITION_VALUE_LENGTH } from '../../../common/constants'; + +/** + * In order to keep this json in sync with https://github.com/elastic/cloud-defend/blob/main/modules/service/policy-schema.json + * Do NOT commit edits to policy_schema.json as part of a PR. Please make the changes in the cloud-defend repo and use the + * make push-policy-schema-kibana command to automate the creation of a PR to sync the changes. + */ +import policySchemaJson from './policy_schema.json'; const { Uri, editor } = monaco; @@ -24,8 +30,25 @@ export const useConfigModel = (configuration: string) => { } }, [configuration]); + // creating a string csv to avoid the next useMemo from re-running regardless of whether + // selector names changed or not. + const selectorNamesCSV = useMemo( + () => json?.selectors?.map((selector: any) => selector.name).join(',') || '', + [json?.selectors] + ); + return useMemo(() => { - const selectorNames = json?.selectors?.map((selector: any) => selector.name) || []; + const schema: any = { ...policySchemaJson }; + + // dynamically setting enum values for response match and exclude properties. + if (schema.$defs.response.properties.match.items) { + const responseProps = schema.$defs.response.properties; + const selectorEnum = { enum: selectorNamesCSV.split(',') }; + responseProps.match.items = selectorEnum; + responseProps.exclude.items = selectorEnum; + } else { + throw new Error('cloud_defend json schema is invalid'); + } setDiagnosticsOptions({ validate: true, @@ -35,112 +58,7 @@ export const useConfigModel = (configuration: string) => { { uri: SCHEMA_URI, fileMatch: [String(modelUri)], - schema: { - type: 'object', - required: ['selectors', 'responses'], - additionalProperties: false, - properties: { - selectors: { - type: 'array', - minItems: 1, - items: { $ref: '#/$defs/selector' }, - }, - responses: { - type: 'array', - minItems: 1, - items: { $ref: '#/$defs/response' }, - }, - }, - $defs: { - selector: { - type: 'object', - required: ['name'], - additionalProperties: false, - anyOf: [ - { required: ['operation'] }, - { required: ['containerImageName'] }, - { required: ['containerImageTag'] }, - { required: ['targetFilePath'] }, - { required: ['orchestratorClusterId'] }, - { required: ['orchestratorClusterName'] }, - { required: ['orchestratorNamespace'] }, - { required: ['orchestratorResourceLabel'] }, - { required: ['orchestratorResourceName'] }, - { required: ['orchestratorType'] }, - ], - properties: { - name: { - type: 'string', - maxLength: MAX_CONDITION_VALUE_LENGTH, - }, - operation: { - type: 'array', - minItems: 1, - items: { enum: ['createExecutable', 'modifyExecutable', 'execMemFd'] }, - }, - containerImageName: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - containerImageTag: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - targetFilePath: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - orchestratorClusterId: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - orchestratorClusterName: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - orchestratorNamespace: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - orchestratorResourceLabel: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - orchestratorResourceName: { - type: 'array', - minItems: 1, - items: { type: 'string', maxLength: MAX_CONDITION_VALUE_LENGTH }, - }, - orchestratorType: { - type: 'array', - minItems: 1, - items: { enum: ['kubernetes'] }, - }, - }, - }, - response: { - type: 'object', - required: ['match', 'actions'], - additionalProperties: false, - properties: { - match: { type: 'array', minItems: 1, items: { enum: selectorNames } }, - exclude: { type: 'array', items: { enum: selectorNames } }, - actions: { - type: 'array', - minItems: 1, - items: { enum: ['alert', 'block'] }, - }, - }, - }, - }, - }, + schema, }, ], }); @@ -148,9 +66,9 @@ export const useConfigModel = (configuration: string) => { let model = editor.getModel(modelUri); if (model === null) { - model = editor.createModel(configuration, 'yaml', modelUri); + model = editor.createModel('', 'yaml', modelUri); } return model; - }, [configuration, json?.selectors]); + }, [selectorNamesCSV]); }; diff --git a/x-pack/plugins/cloud_defend/public/components/policy_settings/translations.ts b/x-pack/plugins/cloud_defend/public/components/policy_settings/translations.ts index 84fb74351e213..8cb10aa562c06 100644 --- a/x-pack/plugins/cloud_defend/public/components/policy_settings/translations.ts +++ b/x-pack/plugins/cloud_defend/public/components/policy_settings/translations.ts @@ -8,10 +8,10 @@ import { i18n } from '@kbn/i18n'; export const enableControl = i18n.translate('xpack.cloudDefend.enableControl', { - defaultMessage: 'Enable BPF/LSM controls', + defaultMessage: 'Enable drift prevention', }); export const enableControlHelp = i18n.translate('xpack.cloudDefend.enableControlHelp', { defaultMessage: - 'Enables BPF/LSM control mechanism, for use with FIM and container drift prevention.', + 'Toggles enablement of drift prevention policy to alert and/or block file operations.', }); diff --git a/x-pack/plugins/cloud_defend/public/types.ts b/x-pack/plugins/cloud_defend/public/types.ts index 3f1704b2cd07e..801f5ee67891e 100755 --- a/x-pack/plugins/cloud_defend/public/types.ts +++ b/x-pack/plugins/cloud_defend/public/types.ts @@ -30,6 +30,8 @@ export enum ControlSelectorCondition { containerImageName = 'containerImageName', containerImageTag = 'containerImageTag', targetFilePath = 'targetFilePath', + ignoreVolumeFiles = 'ignoreVolumeFiles', + ignoreVolumeMounts = 'ignoreVolumeMounts', orchestratorClusterId = 'orchestratorClusterId', orchestratorClusterName = 'orchestratorClusterName', orchestratorNamespace = 'orchestratorNamespace', @@ -39,6 +41,11 @@ export enum ControlSelectorCondition { orchestratorType = 'orchestratorType', } +export enum ControlSelectorBooleanConditions { + ignoreVolumeFiles = 'ignoreVolumeFiles', + ignoreVolumeMounts = 'ignoreVolumeMounts', +} + export enum ControlSelectorOperation { createExecutable = 'createExecutable', modifyExecutable = 'modifyExecutable', @@ -66,6 +73,8 @@ export interface ControlSelector { containerImageName?: string[]; containerImageTag?: string[]; targetFilePath?: string[]; + ignoreVolumeFiles?: boolean; + ignoreVolumeMounts?: boolean; orchestratorClusterId?: string[]; orchestratorClusterName?: string[]; orchestratorNamespace?: string[]; diff --git a/x-pack/plugins/cloud_defend/tsconfig.json b/x-pack/plugins/cloud_defend/tsconfig.json index 630c1ba061a32..f96b98d8c44dd 100755 --- a/x-pack/plugins/cloud_defend/tsconfig.json +++ b/x-pack/plugins/cloud_defend/tsconfig.json @@ -1,12 +1,14 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "target/types", + "outDir": "target/types" }, "include": [ "common/**/*", "public/**/*", - "../../../typings/**/*" + "../../../typings/**/*", + "server/**/*.json", + "public/**/*.json" ], "kbn_references": [ "@kbn/core", @@ -21,6 +23,6 @@ "@kbn/shared-ux-router" ], "exclude": [ - "target/**/*", + "target/**/*" ] } diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts index ceefc2a2b6333..219b551c14260 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts @@ -15,11 +15,15 @@ import { } from '../../../common/constants'; import type { PostureInput } from '../../../common/types'; -export const getMockPolicyAWS = () => getPolicyMock(CLOUDBEAT_AWS); -export const getMockPolicyK8s = () => getPolicyMock(CLOUDBEAT_VANILLA); -export const getMockPolicyEKS = () => getPolicyMock(CLOUDBEAT_EKS); +export const getMockPolicyAWS = () => getPolicyMock(CLOUDBEAT_AWS, 'cspm', 'aws'); +export const getMockPolicyK8s = () => getPolicyMock(CLOUDBEAT_VANILLA, 'kspm', 'self_managed'); +export const getMockPolicyEKS = () => getPolicyMock(CLOUDBEAT_EKS, 'kspm', 'eks'); -const getPolicyMock = (type: PostureInput): NewPackagePolicy => { +const getPolicyMock = ( + type: PostureInput, + posture: string, + deployment: string +): NewPackagePolicy => { const mockPackagePolicy = createNewPackagePolicyMock(); const awsVarsMock = { @@ -44,10 +48,10 @@ const getPolicyMock = (type: PostureInput): NewPackagePolicy => { }, vars: { posture: { - value: type === CLOUDBEAT_VANILLA || type === CLOUDBEAT_EKS ? 'kspm' : 'cspm', + value: posture, type: 'text', }, - deployment: { value: type, type: 'text' }, + deployment: { value: deployment, type: 'text' }, }, inputs: [ { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx index 37d4a13e8a532..ec935f0ffc505 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx @@ -49,6 +49,23 @@ describe('', () => { onChange.mockClear(); }); + it('updates package policy namespace to default when it changes', () => { + const policy = getMockPolicyK8s(); + const { rerender } = render(); + + rerender(); + + // Listen to the 2nd triggered by the test (re-render with new policy namespace) + // The 1st is done on mount to ensure initial state is valid. + expect(onChange).toHaveBeenNthCalledWith(2, { + isValid: true, + updatedPolicy: { + ...policy, + namespace: 'default', + }, + }); + }); + it('renders and updates name field', () => { const policy = getMockPolicyK8s(); const { getByLabelText } = render(); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx index baf3eb538c629..b0a4efa793a77 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { memo, useEffect } from 'react'; +import React, { memo, useCallback, useEffect } from 'react'; import { EuiFieldText, EuiFormRow, EuiSpacer, EuiTitle } from '@elastic/eui'; import type { NewPackagePolicy } from '@kbn/fleet-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -16,7 +16,13 @@ import { CLOUDBEAT_VANILLA, CLOUDBEAT_VULN_MGMT_AWS, } from '../../../common/constants'; -import { getPosturePolicy, getEnabledPostureInput, getPostureInputHiddenVars } from './utils'; +import { + getPosturePolicy, + getEnabledPostureInput, + getPostureInputHiddenVars, + POSTURE_NAMESPACE, + NewPackagePolicyPostureInput, +} from './utils'; import { PolicyTemplateInfo, PolicyTemplateInputSelector, @@ -69,8 +75,10 @@ export const CspPolicyTemplateForm = memo(); const input = getEnabledPostureInput(newPolicy); - const updatePolicy = (updatedPolicy: NewPackagePolicy) => - onChange({ isValid: true, updatedPolicy }); + const updatePolicy = useCallback( + (updatedPolicy: NewPackagePolicy) => onChange({ isValid: true, updatedPolicy }), + [onChange] + ); /** * - Updates policy inputs by user selection @@ -118,6 +126,8 @@ export const CspPolicyTemplateForm = memo {isEditPage && } @@ -164,3 +174,20 @@ CspPolicyTemplateForm.displayName = 'CspPolicyTemplateForm'; // eslint-disable-next-line import/no-default-export export { CspPolicyTemplateForm as default }; + +const useEnsureDefaultNamespace = ({ + newPolicy, + input, + updatePolicy, +}: { + newPolicy: NewPackagePolicy; + input: NewPackagePolicyPostureInput; + updatePolicy: (policy: NewPackagePolicy) => void; +}) => { + useEffect(() => { + if (newPolicy.namespace === POSTURE_NAMESPACE) return; + + const policy = { ...getPosturePolicy(newPolicy, input.type), namespace: POSTURE_NAMESPACE }; + updatePolicy(policy); + }, [newPolicy, input, updatePolicy]); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.test.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.test.ts index aaed63a91da0a..8e7366d9b8664 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.test.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.test.ts @@ -35,7 +35,7 @@ describe('getPosturePolicy', () => { const policy = getPosturePolicy(mockCisAws, 'cloudbeat/cis_k8s'); expect(policy.vars?.posture.value).toBe('kspm'); - expect(policy.vars?.deployment.value).toBe('cloudbeat/cis_k8s'); + expect(policy.vars?.deployment.value).toBe('self_managed'); // Does not change extra vars expect(policy.vars?.extra.value).toBe('value'); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts index 6eb1d3079bb92..86e0a4ec1d054 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts @@ -24,6 +24,9 @@ import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/ import { assert } from '../../../common/utils/helpers'; import { cloudPostureIntegrations } from '../../common/constants'; +// Posture policies only support the default namespace +export const POSTURE_NAMESPACE = 'default'; + type PosturePolicyInput = | { type: typeof CLOUDBEAT_AZURE; policy_template: 'cspm' } | { type: typeof CLOUDBEAT_GCP; policy_template: 'cspm' } @@ -40,8 +43,36 @@ export const isPostureInput = ( SUPPORTED_POLICY_TEMPLATES.includes(input.policy_template as CloudSecurityPolicyTemplate) && SUPPORTED_CLOUDBEAT_INPUTS.includes(input.type as PostureInput); -const getInputPolicyTemplate = (inputs: NewPackagePolicyInput[], inputType: PostureInput) => - inputs.filter(isPostureInput).find((i) => i.type === inputType)!.policy_template; +const getPostureType = (policyTemplateInput: PostureInput) => { + switch (policyTemplateInput) { + case CLOUDBEAT_AWS: + case CLOUDBEAT_AZURE: + case CLOUDBEAT_GCP: + return 'cspm'; + case CLOUDBEAT_VANILLA: + case CLOUDBEAT_EKS: + return 'kspm'; + default: + return 'n/a'; + } +}; + +const getDeploymentType = (policyTemplateInput: PostureInput) => { + switch (policyTemplateInput) { + case CLOUDBEAT_AWS: + return 'aws'; + case CLOUDBEAT_AZURE: + return 'azure'; + case CLOUDBEAT_GCP: + return 'gcp'; + case CLOUDBEAT_VANILLA: + return 'self_managed'; + case CLOUDBEAT_EKS: + return 'eks'; + default: + return 'n/a'; + } +}; const getPostureInput = ( input: NewPackagePolicyInput, @@ -75,12 +106,13 @@ export const getPosturePolicy = ( inputVars?: Record ): NewPackagePolicy => ({ ...newPolicy, + namespace: 'default', // Enable new policy input and disable all others inputs: newPolicy.inputs.map((item) => getPostureInput(item, inputType, inputVars)), // Set hidden policy vars vars: merge({}, newPolicy.vars, { - deployment: { value: inputType }, - posture: { value: getInputPolicyTemplate(newPolicy.inputs, inputType) }, + deployment: { value: getDeploymentType(inputType) }, + posture: { value: getPostureType(inputType) }, }), }); diff --git a/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts b/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts index ad35e96b32f77..c6c2500f78857 100644 --- a/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts +++ b/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts @@ -130,14 +130,24 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record {
- + + + + + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx index cf468953f415c..97b1a1608ab60 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx @@ -19,16 +19,20 @@ import { EuiFlexItem, EuiIcon, EuiPanel, + EuiSelect, EuiText, EuiTextColor, + EuiTitle, } from '@elastic/eui'; import type { InputViewProps, + PagingInfoViewProps, ResultViewProps, + ResultsPerPageViewProps, ResultsViewProps, } from '@elastic/react-search-ui-views'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; +import { FormattedMessage, FormattedHTMLMessage } from '@kbn/i18n-react'; import { indexHealthToHealthColor } from '../../../../shared/constants/health_colors'; @@ -171,3 +175,45 @@ export const InputView: React.FC = ({ getInputProps }) => {
); }; + +export const PagingInfoView: React.FC = ({ start, end, totalResults }) => ( + + + +); + +export const RESULTS_PER_PAGE_OPTIONS = [10, 20, 50]; + +export const ResultsPerPageView: React.FC = ({ + onChange, + options, + value, +}) => ( + + + + + ({ + text: i18n.translate( + 'xpack.enterpriseSearch.content.engine.searchPreview.resultsPerPage.label', + { + defaultMessage: '{value} {value, plural, one {Result} other {Results}}', + values: { value: option }, + } + ), + value: option, + })) ?? [] + } + value={value} + onChange={(evt) => onChange(parseInt(evt.target.value, 10))} + /> + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/constants.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/constants.ts index 35e1942bdc3de..fb490ce35b7fe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/constants.ts @@ -11,7 +11,7 @@ export const FLASH_MESSAGE_TYPES = { success: { color: 'success' as FlashMessageColors, iconType: 'check' }, info: { color: 'primary' as FlashMessageColors, iconType: 'iInCircle' }, warning: { color: 'warning' as FlashMessageColors, iconType: 'alert' }, - error: { color: 'danger' as FlashMessageColors, iconType: 'alert' }, + error: { color: 'danger' as FlashMessageColors, iconType: 'error' }, }; // This is the default amount of time (5 seconds) a toast will last before disappearing diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx index 757e5509773ac..dd1aef467d3dc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx @@ -69,7 +69,7 @@ describe('Toasts', () => { }, { color: 'danger', - iconType: 'alert', + iconType: 'error', title: 'Oh no!', text:
Something went wrong
, id: 'errorToastId', diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts index 6d56c7b202797..25da2c2f728a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts @@ -104,7 +104,7 @@ describe('Flash Message Helpers', () => { expect(FlashMessagesLogic.values.toastMessages).toEqual([ { color: 'danger', - iconType: 'alert', + iconType: 'error', title: 'Something went wrong', id: 'errorToast-1234567890', }, @@ -142,7 +142,7 @@ describe('Flash Message Helpers', () => { expect(FlashMessagesLogic.values.toastMessages).toEqual([ { color: 'danger', - iconType: 'alert', + iconType: 'error', title: 'Something went wrong', text: "Here's some helpful advice on what to do", toastLifeTimeMs: 50000, diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index c95754bc265d7..f380d66d0223c 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -24,6 +24,8 @@ export const USER_SETTINGS_TEMPLATE_SUFFIX = '@custom'; export const FLEET_ELASTIC_AGENT_DETAILS_DASHBOARD_ID = 'elastic_agent-f47f18cc-9c7d-4278-b2ea-a6dee816d395'; + +export const DATASET_VAR_NAME = 'data_stream.dataset'; /* Package rules: | | autoUpdatePackages | diff --git a/x-pack/plugins/fleet/common/constants/routes.ts b/x-pack/plugins/fleet/common/constants/routes.ts index 527eba8cfdb42..7eb00dd89ab0c 100644 --- a/x-pack/plugins/fleet/common/constants/routes.ts +++ b/x-pack/plugins/fleet/common/constants/routes.ts @@ -34,6 +34,7 @@ export const EPM_API_ROUTES = { DELETE_PATTERN: EPM_PACKAGES_ONE, FILEPATH_PATTERN: `${EPM_PACKAGES_ONE}/{filePath*}`, CATEGORIES_PATTERN: `${EPM_API_ROOT}/categories`, + VERIFICATION_KEY_ID: `${EPM_API_ROOT}/verification_key_id`, STATS_PATTERN: `${EPM_PACKAGES_MANY}/{pkgName}/stats`, INFO_PATTERN_DEPRECATED: EPM_PACKAGES_ONE_DEPRECATED, diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 6256e5ab49384..acb1360d39f83 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -252,6 +252,72 @@ ] } }, + "/epm/verification_key_id": { + "get": { + "summary": "Get package signature verification key ID", + "tags": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "body": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true, + "description": "the key ID of the GPG key used to verify package signatures" + } + } + }, + "statusCode": { + "type": "number" + }, + "headers": { + "type": "object" + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/error" + } + }, + "operationId": "packages-get-verification-key-id" + }, + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "pkgName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "pkgVersion", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "filePath", + "in": "path", + "required": true + } + ] + }, "/epm/categories": { "get": { "summary": "Package categories", @@ -2689,7 +2755,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/new_agent_policy" + "$ref": "#/components/schemas/agent_policy_create_request" } } } @@ -2774,7 +2840,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/new_agent_policy" + "$ref": "#/components/schemas/agent_policy_update_request" } } } @@ -5956,60 +6022,6 @@ } } }, - "new_agent_policy": { - "title": "New agent policy", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "namespace": { - "type": "string" - }, - "description": { - "type": "string" - }, - "monitoring_enabled": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "metrics", - "logs" - ] - } - }, - "data_output_id": { - "type": "string", - "nullable": true - }, - "monitoring_output_id": { - "type": "string", - "nullable": true - }, - "fleet_server_host_id": { - "type": "string", - "nullable": true - }, - "download_source_id": { - "type": "string", - "nullable": true - }, - "unenroll_timeout": { - "type": "number" - }, - "inactivity_timeout": { - "type": "number" - } - }, - "required": [ - "name", - "namespace" - ] - }, "new_package_policy": { "title": "New package policy", "type": "object", @@ -6120,83 +6132,238 @@ ] }, "agent_policy": { - "allOf": [ - { - "$ref": "#/components/schemas/new_agent_policy" + "title": "Agent Policy", + "type": "object", + "properties": { + "id": { + "type": "string" }, - { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - }, - "package_policies": { - "description": "This field is present only when retrieving a single agent policy, or when retrieving a list of agent policy with the ?full=true parameter", - "type": "array", - "items": { - "$ref": "#/components/schemas/package_policy" + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "description": { + "type": "string" + }, + "monitoring_enabled": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "metrics", + "logs" + ] + } + }, + "data_output_id": { + "type": "string", + "nullable": true + }, + "monitoring_output_id": { + "type": "string", + "nullable": true + }, + "fleet_server_host_id": { + "type": "string", + "nullable": true + }, + "download_source_id": { + "type": "string", + "nullable": true + }, + "unenroll_timeout": { + "type": "number" + }, + "inactivity_timeout": { + "type": "number" + }, + "package_policies": { + "description": "This field is present only when retrieving a single agent policy, or when retrieving a list of agent policy with the ?full=true parameter", + "type": "array", + "items": { + "$ref": "#/components/schemas/package_policy" + } + }, + "updated_on": { + "type": "string", + "format": "date-time" + }, + "updated_by": { + "type": "string" + }, + "revision": { + "type": "number" + }, + "agents": { + "type": "number" + }, + "agent_features": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "enabled": { + "type": "boolean" } }, - "updated_on": { - "type": "string", - "format": "date-time" - }, - "updated_by": { - "type": "string" - }, - "data_output_id": { - "type": "string", - "nullable": true - }, - "monitoring_output_id": { - "type": "string", - "nullable": true - }, - "fleet_server_host_id": { - "type": "string", - "nullable": true - }, - "download_source_id": { - "type": "string", - "nullable": true - }, - "revision": { - "type": "number" - }, - "agents": { - "type": "number" + "required": [ + "name", + "enabled" + ] + } + } + }, + "required": [ + "id", + "status", + "name", + "namespace" + ] + }, + "agent_policy_create_request": { + "title": "Create agent policy request", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "description": { + "type": "string" + }, + "monitoring_enabled": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "metrics", + "logs" + ] + } + }, + "data_output_id": { + "type": "string", + "nullable": true + }, + "monitoring_output_id": { + "type": "string", + "nullable": true + }, + "fleet_server_host_id": { + "type": "string", + "nullable": true + }, + "download_source_id": { + "type": "string", + "nullable": true + }, + "unenroll_timeout": { + "type": "number" + }, + "inactivity_timeout": { + "type": "number" + }, + "agent_features": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } }, - "agent_features": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - }, - "required": [ - "name", - "enabled" - ] + "required": [ + "name", + "enabled" + ] + } + } + }, + "required": [ + "name", + "namespace" + ] + }, + "agent_policy_update_request": { + "title": "Update agent policy request", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "description": { + "type": "string" + }, + "monitoring_enabled": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "metrics", + "logs" + ] + } + }, + "data_output_id": { + "type": "string", + "nullable": true + }, + "monitoring_output_id": { + "type": "string", + "nullable": true + }, + "fleet_server_host_id": { + "type": "string", + "nullable": true + }, + "download_source_id": { + "type": "string", + "nullable": true + }, + "unenroll_timeout": { + "type": "number" + }, + "inactivity_timeout": { + "type": "number" + }, + "agent_features": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "enabled": { + "type": "boolean" } - } - }, - "required": [ - "id", - "status" - ] + }, + "required": [ + "name", + "enabled" + ] + } } + }, + "required": [ + "name", + "namespace" ] }, "full_agent_policy_output": { diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 1248cbf92e470..7127151e5c2c3 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -155,6 +155,50 @@ paths: operationId: generate-service-token parameters: - $ref: '#/components/parameters/kbn_xsrf' + /epm/verification_key_id: + get: + summary: Get package signature verification key ID + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + body: + type: object + properties: + id: + type: string + nullable: true + description: >- + the key ID of the GPG key used to verify package + signatures + statusCode: + type: number + headers: + type: object + '400': + $ref: '#/components/responses/error' + operationId: packages-get-verification-key-id + parameters: + - schema: + type: string + name: pkgName + in: path + required: true + - schema: + type: string + name: pkgVersion + in: path + required: true + - schema: + type: string + name: filePath + in: path + required: true /epm/categories: get: summary: Package categories @@ -1675,7 +1719,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/new_agent_policy' + $ref: '#/components/schemas/agent_policy_create_request' security: [] parameters: - $ref: '#/components/parameters/kbn_xsrf' @@ -1728,7 +1772,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/new_agent_policy' + $ref: '#/components/schemas/agent_policy_update_request' parameters: - $ref: '#/components/parameters/kbn_xsrf' /agent_policies/{agentPolicyId}/copy: @@ -3797,44 +3841,6 @@ components: type: array items: type: string - new_agent_policy: - title: New agent policy - type: object - properties: - id: - type: string - name: - type: string - namespace: - type: string - description: - type: string - monitoring_enabled: - type: array - items: - type: string - enum: - - metrics - - logs - data_output_id: - type: string - nullable: true - monitoring_output_id: - type: string - nullable: true - fleet_server_host_id: - type: string - nullable: true - download_source_id: - type: string - nullable: true - unenroll_timeout: - type: number - inactivity_timeout: - type: number - required: - - name - - namespace new_package_policy: title: New package policy type: object @@ -3908,61 +3914,171 @@ components: - revision - $ref: '#/components/schemas/new_package_policy' agent_policy: - allOf: - - $ref: '#/components/schemas/new_agent_policy' - - type: object - properties: - id: - type: string - status: - type: string - enum: - - active - - inactive - package_policies: - description: >- - This field is present only when retrieving a single agent - policy, or when retrieving a list of agent policy with the - ?full=true parameter - type: array - items: - $ref: '#/components/schemas/package_policy' - updated_on: - type: string - format: date-time - updated_by: - type: string - data_output_id: - type: string - nullable: true - monitoring_output_id: - type: string - nullable: true - fleet_server_host_id: - type: string - nullable: true - download_source_id: - type: string - nullable: true - revision: - type: number - agents: - type: number - agent_features: - type: array - items: - type: object - properties: - name: - type: string - enabled: - type: boolean - required: - - name - - enabled - required: - - id - - status + title: Agent Policy + type: object + properties: + id: + type: string + name: + type: string + namespace: + type: string + description: + type: string + monitoring_enabled: + type: array + items: + type: string + enum: + - metrics + - logs + data_output_id: + type: string + nullable: true + monitoring_output_id: + type: string + nullable: true + fleet_server_host_id: + type: string + nullable: true + download_source_id: + type: string + nullable: true + unenroll_timeout: + type: number + inactivity_timeout: + type: number + package_policies: + description: >- + This field is present only when retrieving a single agent policy, or + when retrieving a list of agent policy with the ?full=true parameter + type: array + items: + $ref: '#/components/schemas/package_policy' + updated_on: + type: string + format: date-time + updated_by: + type: string + revision: + type: number + agents: + type: number + agent_features: + type: array + items: + type: object + properties: + name: + type: string + enabled: + type: boolean + required: + - name + - enabled + required: + - id + - status + - name + - namespace + agent_policy_create_request: + title: Create agent policy request + type: object + properties: + id: + type: string + name: + type: string + namespace: + type: string + description: + type: string + monitoring_enabled: + type: array + items: + type: string + enum: + - metrics + - logs + data_output_id: + type: string + nullable: true + monitoring_output_id: + type: string + nullable: true + fleet_server_host_id: + type: string + nullable: true + download_source_id: + type: string + nullable: true + unenroll_timeout: + type: number + inactivity_timeout: + type: number + agent_features: + type: array + items: + type: object + properties: + name: + type: string + enabled: + type: boolean + required: + - name + - enabled + required: + - name + - namespace + agent_policy_update_request: + title: Update agent policy request + type: object + properties: + name: + type: string + namespace: + type: string + description: + type: string + monitoring_enabled: + type: array + items: + type: string + enum: + - metrics + - logs + data_output_id: + type: string + nullable: true + monitoring_output_id: + type: string + nullable: true + fleet_server_host_id: + type: string + nullable: true + download_source_id: + type: string + nullable: true + unenroll_timeout: + type: number + inactivity_timeout: + type: number + agent_features: + type: array + items: + type: object + properties: + name: + type: string + enabled: + type: boolean + required: + - name + - enabled + required: + - name + - namespace full_agent_policy_output: title: Full agent policy type: object diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml index 76b6fba16c873..3f56db4174216 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml @@ -1,52 +1,65 @@ -allOf: - - $ref: ./new_agent_policy.yaml - - type: object - properties: - id: - type: string - status: - type: string - enum: - - active - - inactive - package_policies: - description: This field is present only when retrieving a single agent policy, or when retrieving a list of agent policy with the ?full=true parameter - type: array - items: - $ref: ./package_policy.yaml - updated_on: - type: string - format: date-time - updated_by: - type: string - data_output_id: - type: string - nullable: true - monitoring_output_id: - type: string - nullable: true - fleet_server_host_id: - type: string - nullable: true - download_source_id: - type: string - nullable: true - revision: - type: number - agents: - type: number - agent_features: - type: array - items: - type: object - properties: - name: - type: string - enabled: - type: boolean - required: - - name - - enabled - required: - - id - - status +title: Agent Policy +type: object +properties: + id: + type: string + name: + type: string + namespace: + type: string + description: + type: string + monitoring_enabled: + type: array + items: + type: string + enum: + - metrics + - logs + data_output_id: + type: string + nullable: true + monitoring_output_id: + type: string + nullable: true + fleet_server_host_id: + type: string + nullable: true + download_source_id: + type: string + nullable: true + unenroll_timeout: + type: number + inactivity_timeout: + type: number + package_policies: + description: This field is present only when retrieving a single agent policy, or when retrieving a list of agent policy with the ?full=true parameter + type: array + items: + $ref: ./package_policy.yaml + updated_on: + type: string + format: date-time + updated_by: + type: string + revision: + type: number + agents: + type: number + agent_features: + type: array + items: + type: object + properties: + name: + type: string + enabled: + type: boolean + required: + - name + - enabled +required: + - id + - status + - name + - namespace diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy_create_request.yaml similarity index 70% rename from x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_policy.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy_create_request.yaml index 2edab88c70490..fe9fccf1429bb 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_policy.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy_create_request.yaml @@ -1,4 +1,4 @@ -title: New agent policy +title: Create agent policy request type: object properties: id: @@ -32,6 +32,18 @@ properties: type: number inactivity_timeout: type: number + agent_features: + type: array + items: + type: object + properties: + name: + type: string + enabled: + type: boolean + required: + - name + - enabled required: - name - namespace diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy_update_request.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy_update_request.yaml new file mode 100644 index 0000000000000..ea951e0e4e8c4 --- /dev/null +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy_update_request.yaml @@ -0,0 +1,47 @@ +title: Update agent policy request +type: object +properties: + name: + type: string + namespace: + type: string + description: + type: string + monitoring_enabled: + type: array + items: + type: string + enum: + - metrics + - logs + data_output_id: + type: string + nullable: true + monitoring_output_id: + type: string + nullable: true + fleet_server_host_id: + type: string + nullable: true + download_source_id: + type: string + nullable: true + unenroll_timeout: + type: number + inactivity_timeout: + type: number + agent_features: + type: array + items: + type: object + properties: + name: + type: string + enabled: + type: boolean + required: + - name + - enabled +required: + - name + - namespace diff --git a/x-pack/plugins/fleet/common/openapi/entrypoint.yaml b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml index 4ff56806eb0ef..37c33c28b1053 100644 --- a/x-pack/plugins/fleet/common/openapi/entrypoint.yaml +++ b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml @@ -26,6 +26,8 @@ paths: /service_tokens: $ref: paths/service_tokens.yaml # EPM / integrations endpoints + /epm/verification_key_id: + $ref: paths/epm@verification_key_id.yaml /epm/categories: $ref: paths/epm@categories.yaml /epm/packages/limited: diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml index dfe49938c208a..33fd8a2348412 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml @@ -40,7 +40,7 @@ get: type: boolean in: query name: noAgentCount - description: When set to true, do not count how many agents are in the agent policy, this can improve performance if you are searching over a large number of agent policies. The "agents" property will always be 0 if set to true. + description: When set to true, do not count how many agents are in the agent policy, this can improve performance if you are searching over a large number of agent policies. The "agents" property will always be 0 if set to true. description: '' post: @@ -63,7 +63,7 @@ post: content: application/json: schema: - $ref: ../components/schemas/new_agent_policy.yaml + $ref: ../components/schemas/agent_policy_create_request.yaml security: [] parameters: - $ref: ../components/headers/kbn_xsrf.yaml diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml index 0bdcbf38a70fa..4a7e88abcbab8 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml @@ -46,6 +46,6 @@ put: content: application/json: schema: - $ref: ../components/schemas/new_agent_policy.yaml + $ref: ../components/schemas/agent_policy_update_request.yaml parameters: - $ref: ../components/headers/kbn_xsrf.yaml diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml new file mode 100644 index 0000000000000..c9216b85cd78f --- /dev/null +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml @@ -0,0 +1,41 @@ +get: + summary: Get package signature verification key ID + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + body: + type: object + properties: + id: + type: string + nullable: true + description: the key ID of the GPG key used to verify package signatures + statusCode: + type: number + headers: + type: object + '400': + $ref: ../components/responses/error.yaml + operationId: packages-get-verification-key-id +parameters: + - schema: + type: string + name: pkgName + in: path + required: true + - schema: + type: string + name: pkgVersion + in: path + required: true + - schema: + type: string + name: filePath + in: path + required: true diff --git a/x-pack/plugins/fleet/common/services/policy_template.ts b/x-pack/plugins/fleet/common/services/policy_template.ts index c8fa687123fc6..f77aaae664f29 100644 --- a/x-pack/plugins/fleet/common/services/policy_template.ts +++ b/x-pack/plugins/fleet/common/services/policy_template.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { DATASET_VAR_NAME } from '../constants'; import type { RegistryPolicyTemplate, RegistryPolicyInputOnlyTemplate, @@ -17,7 +18,7 @@ import type { } from '../types'; const DATA_STREAM_DATASET_VAR: RegistryVarsEntry = { - name: 'data_stream.dataset', + name: DATASET_VAR_NAME, type: 'text', title: 'Dataset name', description: diff --git a/x-pack/plugins/fleet/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts index 3e6462bdba4d7..0321308e51c82 100644 --- a/x-pack/plugins/fleet/common/services/routes.ts +++ b/x-pack/plugins/fleet/common/services/routes.ts @@ -26,6 +26,10 @@ import { } from '../constants'; export const epmRouteService = { + getVerificationKeyIdPath: () => { + return EPM_API_ROUTES.VERIFICATION_KEY_ID; + }, + getCategoriesPath: () => { return EPM_API_ROUTES.CATEGORIES_PATTERN; }, diff --git a/x-pack/plugins/fleet/common/types/rest_spec/epm.ts b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts index 105558e0d0620..d7321d8218590 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/epm.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts @@ -171,3 +171,6 @@ export interface DeletePackageResponse { response?: AssetReference[]; items: AssetReference[]; } +export interface GetVerificationKeyIdResponse { + id: string | null; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx index 50b585cac9c89..06059eac6a671 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx @@ -21,6 +21,8 @@ import { } from '@elastic/eui'; import { useRouteMatch } from 'react-router-dom'; +import { DATASET_VAR_NAME } from '../../../../../../../../../common/constants'; + import { useConfig, useGetDataStreams } from '../../../../../../../../hooks'; import { mapPackageReleaseToIntegrationCardRelease } from '../../../../../../../../../common/services'; @@ -90,6 +92,10 @@ export const PackagePolicyInputStreamConfig = memo( const isPackagePolicyEdit = !!packagePolicyId; const isInputOnlyPackage = packageInfo.type === 'input'; + const hasDatasetVar = packageInputStream.vars?.some( + (varDef) => varDef.name === DATASET_VAR_NAME + ); + const showPipelinesAndMappings = !isInputOnlyPackage && !hasDatasetVar; useEffect(() => { if (isDefaultDatastream && containerRef.current) { containerRef.current.scrollIntoView(); @@ -297,7 +303,7 @@ export const PackagePolicyInputStreamConfig = memo( ); })} {/* Only show datastream pipelines and mappings on edit and not for input packages*/} - {isPackagePolicyEdit && !isInputOnlyPackage && ( + {isPackagePolicyEdit && showPipelinesAndMappings && ( <> ); } - if (name === 'data_stream.dataset' && packageType === 'input') { + if (name === DATASET_VAR_NAME && packageType === 'input') { return ( { - // TODO move this to parent hook - // If agent policy has changed, update package policy's agent policy ID and namespace - if (agentPolicy && packagePolicy.policy_id !== agentPolicy.id) { - updatePackagePolicy({ - policy_id: agentPolicy.id, - namespace: agentPolicy.namespace, - }); - } - }, [packagePolicy, agentPolicy, packageInfo, updatePackagePolicy]); - const isManaged = packagePolicy.is_managed; return validationResults ? ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/prepare_input_pkg_policy_dataset.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/prepare_input_pkg_policy_dataset.ts index e4f1fae4419c1..413368772101a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/prepare_input_pkg_policy_dataset.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/prepare_input_pkg_policy_dataset.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { DATASET_VAR_NAME } from '../../../../../../../common/constants'; + import type { NewPackagePolicy } from '../../../../types'; export function prepareInputPackagePolicyDataset(newPolicy: NewPackagePolicy): { @@ -27,16 +29,16 @@ export function prepareInputPackagePolicyDataset(newPolicy: NewPackagePolicy): { const newStreams = streams.map((stream) => { if ( !stream.vars || - !stream.vars['data_stream.dataset'] || - !stream.vars['data_stream.dataset'].value?.package + !stream.vars[DATASET_VAR_NAME] || + !stream.vars[DATASET_VAR_NAME].value?.package ) { return stream; } - const datasetVar = stream.vars['data_stream.dataset']; + const datasetVar = stream.vars[DATASET_VAR_NAME]; forceCreateNeeded = datasetVar.value?.package !== newPolicy?.package?.name; - stream.vars['data_stream.dataset'] = { + stream.vars[DATASET_VAR_NAME] = { ...datasetVar, value: datasetVar.value?.dataset, }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx index d57b8cff64a84..3128bec1a8bbf 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx @@ -10,7 +10,7 @@ import type { RenderHookResult } from '@testing-library/react-hooks'; import type { TestRenderer } from '../../../../../../../mock'; import { createFleetTestRendererMock } from '../../../../../../../mock'; -import type { PackageInfo } from '../../../../../types'; +import type { AgentPolicy, PackageInfo } from '../../../../../types'; import { sendGetPackagePolicies } from '../../../../../hooks'; @@ -94,6 +94,43 @@ describe('useOnSubmit', () => { }); }); + it('should set package policy id and namespace when agent policy changes', () => { + act(() => { + renderResult.result.current.updateAgentPolicy({ + id: 'some-id', + namespace: 'default', + } as AgentPolicy); + }); + + expect(renderResult.result.current.packagePolicy).toEqual({ + policy_id: 'some-id', + namespace: 'default', + description: '', + enabled: true, + inputs: [], + name: 'apache-1', + package: { + name: 'apache', + title: 'Apache', + version: '1.0.0', + }, + vars: { + 'Advanced var': { + type: 'bool', + value: true, + }, + 'Required var': { + type: 'bool', + value: undefined, + }, + 'Show user var': { + type: 'string', + value: 'showUserVarVal', + }, + }, + }); + }); + it('should set index 1 name to package policy on init if no package policies exist for this package', () => { // waitFor(() => { // expect(renderResult.getByDisplayValue('apache-1')).toBeInTheDocument(); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx index 8d7259a77767f..9e77b746214e1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx @@ -219,6 +219,15 @@ export function useOnSubmit({ init(); }, [packageInfo, agentPolicy, updatePackagePolicy, integrationToEnable, isInitialized]); + useEffect(() => { + if (agentPolicy && packagePolicy.policy_id !== agentPolicy.id) { + updatePackagePolicy({ + policy_id: agentPolicy.id, + namespace: agentPolicy.namespace, + }); + } + }, [packagePolicy, agentPolicy, updatePackagePolicy]); + const onSaveNavigate = useOnSaveNavigate({ packagePolicy, queryParamsPolicyId, diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx index 5ab6a7b0938d5..2898b1e241f1e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx @@ -278,18 +278,23 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ ); } - const replaceStepConfigurePackagePolicy = replaceDefineStepView && packageInfo?.name && ( - - - - ); + const replaceStepConfigurePackagePolicy = + replaceDefineStepView && packageInfo?.name ? ( + !isInitialized ? ( + + ) : ( + + + + ) + ) : undefined; const stepConfigurePackagePolicy = useMemo( () => diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx index b9c69d083d21d..a4543005cc9b9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx @@ -7,6 +7,8 @@ import { omit } from 'lodash'; +import { DATASET_VAR_NAME } from '../../../../../../common/constants'; + import { agentPolicyRouteService, packagePolicyRouteService } from '../../../services'; import { generateInputId } from '../../../../../../common/services/simplified_package_policy_helper'; import type { @@ -105,8 +107,8 @@ function formatVars(vars: NewPackagePolicy['inputs'][number]['vars']) { } return Object.entries(vars).reduce((acc, [varKey, varRecord]) => { - // the data_stream.dataset var uses an internal format before we send it - if (varKey === 'data_stream.dataset' && varRecord?.value?.dataset) { + // the dataset var uses an internal format before we send it + if (varKey === DATASET_VAR_NAME && varRecord?.value?.dataset) { acc[varKey] = varRecord?.value.dataset; } else { acc[varKey] = varRecord?.value; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/constants.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/constants.tsx index 9f5cf41ecbcde..bee26f7c5b067 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/constants.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/constants.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { DATASET_VAR_NAME } from '../../../../../../../../common/constants'; + import type { AgentLogsState } from './agent_logs'; export const AGENT_LOG_INDEX_PATTERN = 'logs-elastic_agent-*,logs-elastic_agent.*-*'; @@ -21,7 +23,7 @@ export const AGENT_ID_FIELD = { type: 'string', }; export const DATASET_FIELD = { - name: 'data_stream.dataset', + name: DATASET_VAR_NAME, type: 'string', aggregatable: true, searchable: true, diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx index 101de2a30cef5..74580fede42bf 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx @@ -133,7 +133,7 @@ function usePackageInstall({ />, { theme$ } ), - iconType: 'alert', + iconType: 'error', }); } else { setPackageInstallStatus({ name, status: InstallStatus.installed, version }); @@ -224,7 +224,7 @@ function usePackageInstall({ />, { theme$ } ), - iconType: 'alert', + iconType: 'error', }); } else { setPackageInstallStatus({ name, status: InstallStatus.notInstalled, version: null }); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx index 94a2a223b122a..8100f07e192ea 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx @@ -32,6 +32,8 @@ import { entries } from '../../../../../types'; import { useGetCategoriesQuery } from '../../../../../hooks'; import { AssetTitleMap, DisplayedAssets, ServiceTitleMap } from '../../../constants'; +import { ChangelogModal } from '../settings/changelog_modal'; + import { NoticeModal } from './notice_modal'; import { LicenseModal } from './license_modal'; @@ -71,13 +73,18 @@ export const Details: React.FC = memo(({ packageInfo }) => { const [isNoticeModalOpen, setIsNoticeModalOpen] = useState(false); const toggleNoticeModal = useCallback(() => { - setIsNoticeModalOpen(!isNoticeModalOpen); - }, [isNoticeModalOpen]); + setIsNoticeModalOpen((currentState) => !currentState); + }, []); const [isLicenseModalOpen, setIsLicenseModalOpen] = useState(false); const toggleLicenseModal = useCallback(() => { - setIsLicenseModalOpen(!isLicenseModalOpen); - }, [isLicenseModalOpen]); + setIsLicenseModalOpen((currentState) => !currentState); + }, []); + + const [isChangelogModalOpen, setIsChangelogModalOpen] = useState(false); + const toggleChangelogModal = useCallback(() => { + setIsChangelogModalOpen((currentState) => !currentState); + }, []); const listItems = useMemo(() => { // Base details: version and categories @@ -201,6 +208,21 @@ export const Details: React.FC = memo(({ packageInfo }) => { }); } + items.push({ + title: ( + + + + ), + description: ( + <> +

+ View Changelog +

+ + ), + }); + return items; }, [ packageCategories, @@ -214,6 +236,7 @@ export const Details: React.FC = memo(({ packageInfo }) => { packageInfo.version, toggleLicenseModal, toggleNoticeModal, + toggleChangelogModal, ]); return ( @@ -232,6 +255,15 @@ export const Details: React.FC = memo(({ packageInfo }) => { /> )} + + {isChangelogModalOpen && ( + + )} + diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx index 53806c5b4d98c..888903a293e14 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx @@ -15,7 +15,11 @@ import { isPackagePrerelease, } from '../../../../../../../../common/services'; -import { useFleetStatus, useLink, useStartServices } from '../../../../../../../hooks'; +import { + useGetPackageVerificationKeyId, + useLink, + useStartServices, +} from '../../../../../../../hooks'; import { isPackageUnverified } from '../../../../../../../services'; import type { PackageInfo, RegistryPolicyTemplate } from '../../../../../types'; @@ -115,7 +119,7 @@ export const OverviewPage: React.FC = memo( () => integrationInfo?.screenshots || packageInfo.screenshots || [], [integrationInfo, packageInfo.screenshots] ); - const { packageVerificationKeyId } = useFleetStatus(); + const { packageVerificationKeyId } = useGetPackageVerificationKeyId(); const isUnverified = isPackageUnverified(packageInfo, packageVerificationKeyId); const isPrerelease = isPackagePrerelease(packageInfo.version); return ( diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/changelog_modal.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/changelog_modal.tsx new file mode 100644 index 0000000000000..119a236c18b7a --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/changelog_modal.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { + EuiCodeBlock, + EuiModal, + EuiModalBody, + EuiModalHeader, + EuiModalFooter, + EuiModalHeaderTitle, + EuiButton, + EuiSkeletonText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import { useGetFileByPathQuery, useStartServices } from '../../../../../hooks'; + +import { getFormattedChangelog } from '../utils'; + +export interface ChangeLogParams { + version: string; + changes: Array<{ + description: string; + link: string; + type: string; + }>; +} + +interface Props { + latestVersion: string; + currentVersion?: string; + packageName: string; + onClose: () => void; +} + +export const ChangelogModal: React.FunctionComponent = ({ + latestVersion, + currentVersion, + packageName, + onClose, +}) => { + const { notifications } = useStartServices(); + + const { + data: changelogResponse, + error: changelogError, + isLoading, + } = useGetFileByPathQuery(`/package/${packageName}/${latestVersion}/changelog.yml`); + const changelogText = changelogResponse?.data; + + // currentVersion is used to display the changelog up to the current installed version, when there is a newer one available + const finalChangelog = currentVersion + ? getFormattedChangelog(changelogText, latestVersion, currentVersion) + : getFormattedChangelog(changelogText, latestVersion); + + if (changelogError) { + notifications.toasts.addError(changelogError, { + title: i18n.translate('xpack.fleet.epm.errorLoadingChangelog', { + defaultMessage: 'Error loading changelog information', + }), + }); + } + + return ( + + + {'Changelog'} + + + + {finalChangelog} + + + + + + + + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx index 966b0419285ec..b7ec3019b66a6 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx @@ -18,6 +18,7 @@ import { EuiText, EuiSpacer, EuiLink, + EuiPortal, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -48,6 +49,7 @@ import { InstallButton } from './install_button'; import { ReinstallButton } from './reinstall_button'; import { UpdateButton } from './update_button'; import { UninstallButton } from './uninstall_button'; +import { ChangelogModal } from './changelog_modal'; const SettingsTitleCell = styled.td` padding-right: ${(props) => props.theme.eui.euiSizeXL}; @@ -62,7 +64,13 @@ const NoteLabel = () => ( /> ); -const UpdatesAvailableMsg = ({ latestVersion }: { latestVersion: string }) => ( +const UpdatesAvailableMsg = ({ + latestVersion, + toggleChangelogModal, +}: { + latestVersion: string; + toggleChangelogModal: () => void; +}) => ( ( defaultMessage: 'New version available', })} > - + + + + + +

+ {'View changelog.'} +

+
+
); @@ -101,6 +118,11 @@ interface Props { export const SettingsPage: React.FC = memo(({ packageInfo, theme$ }: Props) => { const { name, title, latestVersion, version, keepPoliciesUpToDate } = packageInfo; const [isUpgradingPackagePolicies, setIsUpgradingPackagePolicies] = useState(false); + const [isChangelogModalOpen, setIsChangelogModalOpen] = useState(false); + + const toggleChangelogModal = useCallback(() => { + setIsChangelogModalOpen(!isChangelogModalOpen); + }, [isChangelogModalOpen]); const getPackageInstallStatus = useGetPackageInstallStatus(); const { data: packagePoliciesData } = useGetPackagePoliciesQuery({ @@ -220,98 +242,218 @@ export const SettingsPage: React.FC = memo(({ packageInfo, theme$ }: Prop ); return ( - - - - - -

- -

-
- - {installedVersion !== null && ( -
- -

- -

-
- - - - - - + + + + + +

+ +

+
+ + {installedVersion !== null && ( +
+ +

+ +

+
+ +
+ + + + + + + + + + + + + + +
+ + {installedVersion} + +
+ + {latestVersion} + +
+ {shouldShowKeepPoliciesUpToDateSwitch && ( + <> + + + + )} + + {(updateAvailable || isUpgradingPackagePolicies) && ( + <> + + +

+ - - - - {installedVersion} - - - - - +

+ + )} +
+ )} + {!hideInstallOptions && !isUpdating && ( +
+ + {installationStatus === InstallStatus.notInstalled || + installationStatus === InstallStatus.installing ? ( +
+ +

+ +

+
+ +

- - - - {latestVersion} - - - - - - {shouldShowKeepPoliciesUpToDateSwitch && ( - <> - - - - )} - - {(updateAvailable || isUpgradingPackagePolicies) && ( - <> - - -

- -

- - )} -
- )} - {!hideInstallOptions && !isUpdating && ( -
- - {installationStatus === InstallStatus.notInstalled || - installationStatus === InstallStatus.installing ? ( +

+ + +

+ +

+
+
+
+ ) : ( + <> + + + +

+ +

+
+
+ + + + +
+ +
+
+ {packageHasUsages && ( + + + , + }} + /> + + + )} +
+ + + + +

+ +

+
+
+ + + + +
+ +
+
+
+ + )} +
+ )} + {hideInstallOptions && isViewingOldPackage && !isUpdating && ( +
+

@@ -326,138 +468,33 @@ export const SettingsPage: React.FC = memo(({ packageInfo, theme$ }: Prop

- -

- - -

- -

-
-
-

- ) : ( - <> - - - -

- -

-
-
- - - - -
- -
-
- {packageHasUsages && ( - - - , - }} - /> - - - )} -
- - - - -

- -

-
-
- + , + }} /> - - -
- -
-
-
- - )} -
- )} - {hideInstallOptions && isViewingOldPackage && !isUpdating && ( -
- -
- -

- -

-
- -

- - , - }} - /> - -

+ +

+
- - )} -
-
-
+ )} +
+
+
+ + {isChangelogModalOpen && ( + + )} + + ); }); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/changelog_utils.test.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/changelog_utils.test.ts new file mode 100644 index 0000000000000..5a29eba562a75 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/changelog_utils.test.ts @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { filterYamlChangelog } from '.'; + +describe('filterYamlChangelog', () => { + const changelogText = ` +- version: "2.4.0" + changes: + - description: Update package to ECS 8.6.0. + type: enhancement + link: https://github.com/elastic/integrations/pull/4576 +- version: "2.3.0" + changes: + - description: Added support for GCS input. + type: enhancement + link: https://github.com/elastic/integrations/pull/4728 +- version: "2.2.0" + changes: + - description: Update package to ECS 8.5.0. + type: enhancement + link: https://github.com/elastic/integrations/pull/4285 +- version: "2.1.2" + changes: + - description: Remove duplicate fields. + type: bugfix + link: https://github.com/elastic/integrations/pull/4399`; + + it('should return the changelog from latest to current version', () => { + expect(filterYamlChangelog(changelogText, `2.4.0`, `2.2.0`)).toEqual([ + { + version: '2.4.0', + changes: [ + { + description: 'Update package to ECS 8.6.0.', + link: 'https://github.com/elastic/integrations/pull/4576', + type: 'enhancement', + }, + ], + }, + { + version: '2.3.0', + changes: [ + { + description: 'Added support for GCS input.', + link: 'https://github.com/elastic/integrations/pull/4728', + type: 'enhancement', + }, + ], + }, + { + version: '2.2.0', + changes: [ + { + description: 'Update package to ECS 8.5.0.', + link: 'https://github.com/elastic/integrations/pull/4285', + type: 'enhancement', + }, + ], + }, + ]); + }); + + it('should return the changelog to latest version when there is no current version defined', () => { + expect(filterYamlChangelog(changelogText, `2.4.0`)).toEqual([ + { + version: '2.4.0', + changes: [ + { + description: 'Update package to ECS 8.6.0.', + link: 'https://github.com/elastic/integrations/pull/4576', + type: 'enhancement', + }, + ], + }, + { + version: '2.3.0', + changes: [ + { + description: 'Added support for GCS input.', + link: 'https://github.com/elastic/integrations/pull/4728', + type: 'enhancement', + }, + ], + }, + { + version: '2.2.0', + changes: [ + { + description: 'Update package to ECS 8.5.0.', + link: 'https://github.com/elastic/integrations/pull/4285', + type: 'enhancement', + }, + ], + }, + { + version: '2.1.2', + changes: [ + { + description: 'Remove duplicate fields.', + link: 'https://github.com/elastic/integrations/pull/4399', + type: 'bugfix', + }, + ], + }, + ]); + }); + + it('should return empty array if changelog text is undefined', () => { + expect(filterYamlChangelog(undefined, `2.4.0`, `2.2.0`)).toEqual([]); + }); + it('should return empty array if changelog text is null', () => { + expect(filterYamlChangelog(null, `2.4.0`, `2.2.0`)).toEqual([]); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/changelog_utils.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/changelog_utils.ts new file mode 100644 index 0000000000000..7860704bb208a --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/changelog_utils.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { safeLoad } from 'js-yaml'; + +import semverGte from 'semver/functions/gte'; +import semverLte from 'semver/functions/lte'; + +import type { ChangeLogParams } from '../settings/changelog_modal'; + +export const formatChangelog = (parsedChangelog: ChangeLogParams[]) => { + if (!parsedChangelog) return ''; + + return parsedChangelog.reduce((acc, val) => { + acc += `Version: ${val.version}\nChanges:\n Type: ${val.changes[0].type}\n Description: ${val.changes[0].description}\n Link: ${val.changes[0].link}\n\n`; + return acc; + }, ''); +}; + +// Exported for testing +export const filterYamlChangelog = ( + changelogText: string | null | undefined, + latestVersion: string, + currentVersion?: string +) => { + const parsedChangelog: ChangeLogParams[] = changelogText ? safeLoad(changelogText) : []; + + if (!currentVersion) return parsedChangelog.filter((e) => semverLte(e.version, latestVersion)); + + return parsedChangelog.filter( + (e) => semverLte(e.version, latestVersion) && semverGte(e.version, currentVersion) + ); +}; + +export const getFormattedChangelog = ( + changelogText: string | null | undefined, + latestVersion: string, + currentVersion?: string +) => { + const parsed = filterYamlChangelog(changelogText, latestVersion, currentVersion); + return formatChangelog(parsed); +}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/index.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/index.ts index 020e115f2309a..fa39a2f963396 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/index.ts +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/utils/index.ts @@ -6,3 +6,4 @@ */ export { getInstallPkgRouteOptions } from './get_install_route_options'; +export { getFormattedChangelog, filterYamlChangelog } from './changelog_utils'; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/installed_packages.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/installed_packages.tsx index 695646d20f6a6..04b219875a0c6 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/installed_packages.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/installed_packages.tsx @@ -14,7 +14,12 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { pagePathGetters } from '../../../../constants'; -import { useBreadcrumbs, useLink, useStartServices, useFleetStatus } from '../../../../hooks'; +import { + useBreadcrumbs, + useLink, + useStartServices, + useGetPackageVerificationKeyId, +} from '../../../../hooks'; import { PackageListGrid } from '../../components/package_list_grid'; import type { PackageListItem } from '../../../../types'; @@ -121,7 +126,7 @@ export const InstalledPackages: React.FC<{ }> = ({ installedPackages, isLoading }) => { useBreadcrumbs('integrations_installed'); - const { packageVerificationKeyId } = useFleetStatus(); + const { packageVerificationKeyId } = useGetPackageVerificationKeyId(); const { getHref, getAbsolutePath } = useLink(); diff --git a/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx b/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx index 95067a3158d25..d0f3414a4d016 100644 --- a/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx +++ b/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx @@ -19,7 +19,6 @@ interface FleetStatusState { error?: Error; missingRequirements?: GetFleetStatusResponse['missing_requirements']; missingOptionalFeatures?: GetFleetStatusResponse['missing_optional_features']; - packageVerificationKeyId?: GetFleetStatusResponse['package_verification_key_id']; } interface FleetStatus extends FleetStatusState { @@ -60,7 +59,6 @@ export const FleetStatusProvider: React.FC = ({ children }) => { isReady: res.data?.isReady ?? false, missingRequirements: res.data?.missing_requirements, missingOptionalFeatures: res.data?.missing_optional_features, - packageVerificationKeyId: res.data?.package_verification_key_id, })); } catch (error) { setState((s) => ({ ...s, isLoading: false, error })); diff --git a/x-pack/plugins/fleet/public/hooks/use_request/epm.ts b/x-pack/plugins/fleet/public/hooks/use_request/epm.ts index dc3b5d1048e7f..1a50be67099a5 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/epm.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/epm.ts @@ -24,6 +24,7 @@ import type { DeletePackageResponse, UpdatePackageRequest, UpdatePackageResponse, + GetVerificationKeyIdResponse, } from '../../types'; import type { FleetErrorResponse, GetStatsResponse } from '../../../common/types'; @@ -142,6 +143,22 @@ export const useGetPackageStats = (pkgName: string) => { }); }; +export const useGetPackageVerificationKeyId = () => { + const { data, ...rest } = useQuery( + ['verification_key_id'], + () => + sendRequestForRq({ + path: epmRouteService.getVerificationKeyIdPath(), + method: 'get', + }) + ); + + return { + packageVerificationKeyId: data?.id || undefined, + ...rest, + }; +}; + export const sendGetPackageInfoByKey = ( pkgName: string, pkgVersion?: string, diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 1f986e8e27b12..530b8701ab9f4 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -113,6 +113,7 @@ export type { ServiceName, GetCategoriesRequest, GetCategoriesResponse, + GetVerificationKeyIdResponse, GetPackagesRequest, GetPackagesResponse, GetLimitedPackagesResponse, diff --git a/x-pack/plugins/fleet/server/routes/epm/handlers.ts b/x-pack/plugins/fleet/server/routes/epm/handlers.ts index d0fef5e241708..8bacf87284271 100644 --- a/x-pack/plugins/fleet/server/routes/epm/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/epm/handlers.ts @@ -24,6 +24,7 @@ import type { IBulkInstallPackageHTTPError, GetStatsResponse, UpdatePackageResponse, + GetVerificationKeyIdResponse, } from '../../../common/types'; import type { GetCategoriesRequestSchema, @@ -58,6 +59,7 @@ import { getArchiveEntry } from '../../services/epm/archive/cache'; import { getAsset } from '../../services/epm/archive/storage'; import { getPackageUsageStats } from '../../services/epm/packages/get'; import { updatePackage } from '../../services/epm/packages/update'; +import { getGpgKeyIdOrUndefined } from '../../services/epm/packages/package_verification'; const CACHE_CONTROL_10_MINUTES_HEADER: HttpResponseOptions['headers'] = { 'cache-control': 'max-age=600', @@ -414,3 +416,19 @@ export const deletePackageHandler: FleetRequestHandler< return defaultFleetErrorHandler({ error, response }); } }; + +export const getVerificationKeyIdHandler: FleetRequestHandler = async ( + context, + request, + response +) => { + try { + const packageVerificationKeyId = await getGpgKeyIdOrUndefined(); + const body: GetVerificationKeyIdResponse = { + id: packageVerificationKeyId || null, + }; + return response.ok({ body }); + } catch (error) { + return defaultFleetErrorHandler({ error, response }); + } +}; diff --git a/x-pack/plugins/fleet/server/routes/epm/index.ts b/x-pack/plugins/fleet/server/routes/epm/index.ts index 950dca7009355..5c2a34cd90551 100644 --- a/x-pack/plugins/fleet/server/routes/epm/index.ts +++ b/x-pack/plugins/fleet/server/routes/epm/index.ts @@ -53,6 +53,7 @@ import { bulkInstallPackagesFromRegistryHandler, getStatsHandler, updatePackageHandler, + getVerificationKeyIdHandler, } from './handlers'; const MAX_FILE_SIZE_BYTES = 104857600; // 100MB @@ -187,6 +188,17 @@ export const registerRoutes = (router: FleetAuthzRouter) => { deletePackageHandler ); + router.get( + { + path: EPM_API_ROUTES.VERIFICATION_KEY_ID, + validate: false, + fleetAuthz: { + integrations: { readPackageInfo: true }, + }, + }, + getVerificationKeyIdHandler + ); + // deprecated since 8.0 router.get( { diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts index 44e0014630d15..2f148a2f10805 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts @@ -447,6 +447,27 @@ describe('EPM template', () => { expect(mappings).toEqual(keywordWithMultiFieldsMapping); }); + it('tests processing date field with format', () => { + const dateWithFormatYml = ` +- name: dateWithFormat + type: date + date_format: yyyy-MM-dd +`; + + const dateWithMapping = { + properties: { + dateWithFormat: { + type: 'date', + format: 'yyyy-MM-dd', + }, + }, + }; + const fields: Field[] = safeLoad(dateWithFormatYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(mappings).toEqual(dateWithMapping); + }); + it('tests processing wildcard field with multi fields', () => { const keywordWithMultiFieldsLiteralYml = ` - name: keywordWithMultiFields diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index ac7afd143666b..dacdfae720ccf 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -322,6 +322,10 @@ function _generateMappings( fieldProps.type = 'alias'; fieldProps.path = field.path; break; + case 'date': + const dateMappings = generateDateMapping(field); + fieldProps = { ...fieldProps, ...dateMappings, type: 'date' }; + break; default: fieldProps.type = type; } @@ -423,6 +427,14 @@ function generateWildcardMapping(field: Field): IndexTemplateMapping { return mapping; } +function generateDateMapping(field: Field): IndexTemplateMapping { + const mapping: IndexTemplateMapping = {}; + if (field.date_format) { + mapping.format = field.date_format; + } + return mapping; +} + /** * Generates the template name out of the given information */ diff --git a/x-pack/plugins/fleet/server/services/epm/fields/field.ts b/x-pack/plugins/fleet/server/services/epm/fields/field.ts index b8af566463896..4bec0604cca4f 100644 --- a/x-pack/plugins/fleet/server/services/epm/fields/field.ts +++ b/x-pack/plugins/fleet/server/services/epm/fields/field.ts @@ -17,6 +17,7 @@ export interface Field { description?: string; value?: string; format?: string; + date_format?: string; fields?: Fields; enabled?: boolean; path?: string; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index a3d087d828b01..0b5b86407100e 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -45,7 +45,7 @@ import type { PackageVerificationResult, RegistryDataStream, } from '../../../types'; -import { AUTO_UPGRADE_POLICIES_PACKAGES } from '../../../../common/constants'; +import { AUTO_UPGRADE_POLICIES_PACKAGES, DATASET_VAR_NAME } from '../../../../common/constants'; import { FleetError, PackageOutdatedError, PackagePolicyValidationError } from '../../../errors'; import { PACKAGES_SAVED_OBJECT_TYPE, MAX_TIME_COMPLETE_INSTALL } from '../../../constants'; import { dataStreamService, licenseService } from '../..'; @@ -1033,7 +1033,7 @@ export async function installAssetsForInputPackagePolicy(opts: { const paths = await getArchiveFilelist(pkgInfo); if (!paths) throw new Error('No paths found for '); - const datasetName = packagePolicy.inputs[0].streams[0].vars?.['data_stream.dataset']?.value; + const datasetName = packagePolicy.inputs[0].streams[0].vars?.[DATASET_VAR_NAME]?.value; const [dataStream] = getNormalizedDataStreams(pkgInfo, datasetName); const existingDataStreams = await dataStreamService.getMatchingDataStreams(esClient, { type: dataStream.type, diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 282cb85b2b895..8561b14dd9ded 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -42,6 +42,7 @@ import { FLEET_APM_PACKAGE, outputType, PACKAGES_SAVED_OBJECT_TYPE, + DATASET_VAR_NAME, } from '../../common/constants'; import type { PostDeletePackagePoliciesResponse, @@ -2147,17 +2148,16 @@ export function _validateRestrictedFieldsNotModifiedOrThrow(opts: { ); if ( oldStream && - oldStream?.vars?.['data_stream.dataset'] && - oldStream?.vars['data_stream.dataset']?.value !== - stream?.vars?.['data_stream.dataset']?.value + oldStream?.vars?.[DATASET_VAR_NAME] && + oldStream?.vars[DATASET_VAR_NAME]?.value !== stream?.vars?.[DATASET_VAR_NAME]?.value ) { // seeing this error in dev? Package policy must be called with prepareInputPackagePolicyDataset function first in UI code appContextService .getLogger() .debug( `Rejecting package policy update due to dataset change, old val '${ - oldStream?.vars['data_stream.dataset']?.value - }, new val '${JSON.stringify(stream?.vars?.['data_stream.dataset']?.value)}'` + oldStream?.vars[DATASET_VAR_NAME]?.value + }, new val '${JSON.stringify(stream?.vars?.[DATASET_VAR_NAME]?.value)}'` ); throw new PackagePolicyValidationError( i18n.translate('xpack.fleet.updatePackagePolicy.datasetCannotBeModified', { diff --git a/x-pack/plugins/infra/kibana.jsonc b/x-pack/plugins/infra/kibana.jsonc index 88b8384c7eb18..e17d5bac5a98f 100644 --- a/x-pack/plugins/infra/kibana.jsonc +++ b/x-pack/plugins/infra/kibana.jsonc @@ -24,7 +24,6 @@ "ruleRegistry", "security", "share", - "spaces", "triggersActionsUi", "unifiedSearch", "usageCollection", diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx index d62a22258cc01..df24f7cfac10c 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_stat.tsx @@ -70,7 +70,7 @@ const tooltipContent = { 'xpack.ml.dataframe.analytics.regressionExploration.msleTooltipContent', { defaultMessage: - 'Average squared difference between the logarithm of the predicted values and the logarithm of the actual (ground truth) value', + 'Average squared difference between the logarithm of the predicted values and the logarithm of the actual (ground truth) value.', } ), [REGRESSION_STATS.R_SQUARED]: i18n.translate( diff --git a/x-pack/plugins/observability/dev_docs/slo.md b/x-pack/plugins/observability/dev_docs/slo.md index bd9dcc96c4c59..595eac175ae57 100644 --- a/x-pack/plugins/observability/dev_docs/slo.md +++ b/x-pack/plugins/observability/dev_docs/slo.md @@ -6,11 +6,11 @@ Add the feature flag: `xpack.observability.unsafe.slo.enabled: true` in your Kib We currently support the following SLI: -- APM Transaction Error Rate (Availability) -- APM Transaction Duration (Latency) +- APM Transaction Error Rate, known as APM Availability +- APM Transaction Duration, known as APM Latency - Custom KQL -For the APM SLIs, customer can provide the service, environment, transaction name and type to configure them. For the **Duration** SLI, a threshold in microsecond needs to be provided to discriminate the good and bad responses (events). For the **Error Rate** SLI, a list of good status codes needs to be provided to discriminate the good and bad responses (events). +For the APM SLIs, customer can provide the service, environment, transaction name and type to configure them. For the **APM Latency** SLI, a threshold in milliseconds needs to be provided to discriminate the good and bad responses (events). For the **APM Availability** SLI, a list of good status codes needs to be provided to discriminate the good and bad responses (events). The API supports an optional kql filter to further filter the apm data. The **custom KQL** SLI requires an index pattern, an optional filter query, a numerator query, and denominator query. @@ -43,9 +43,9 @@ If a **timeslices** budgeting method is used, we also need to define the **times The default settings should be sufficient for most users, but if needed, the following properties can be overwritten: -- timestampField: The date time field to use from the source index -- syncDelay: The ingest delay in the source data -- frequency: How often do we query the source data +- **timestampField**: The date time field to use from the source index +- **syncDelay**: The ingest delay in the source data +- **frequency**: How often do we query the source data ## Example diff --git a/x-pack/plugins/observability/docs/openapi/slo/README.md b/x-pack/plugins/observability/docs/openapi/slo/README.md new file mode 100644 index 0000000000000..e128dd32a38b9 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/README.md @@ -0,0 +1,34 @@ +# OpenAPI (Experimental) + +The current self-contained spec file is [as YAML](https://raw.githubusercontent.com/elastic/kibana/master/x-pack/plugins/obserbability/docs/openapi/slo/bundled.yaml) and can be used for online tools like those found at . +This spec is experimental and may be incomplete or change later. + +A guide about the OpenApi specification can be found at [https://swagger.io/docs/specification/about/](https://swagger.io/docs/specification/about/). + +## The `openapi/slo` folder + +* `entrypoint.yaml` is the overview file which pulls together all the paths and components. +* [Paths](paths/README.md): this defines each endpoint. A path can have one operation per http method. +* [Components](components/README.md): Reusable components + +## Tools + +It is possible to validate the docs before bundling them with the following +command in the `x-pack/plugins/observability/docs/openapi/slo` folder: + + ```bash + npx swagger-cli validate entrypoint.yaml + ``` + +Then you can generate the `bundled` files by running the following commands: + + ```bash + npx @redocly/cli bundle entrypoint.yaml --output bundled.yaml --ext yaml + npx @redocly/cli bundle entrypoint.yaml --output bundled.json --ext json + ``` + +After generating the json bundle ensure that it is also valid by running the following command: + + ```bash + npx @redocly/cli lint bundled.json + ``` diff --git a/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml b/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml new file mode 100644 index 0000000000000..9e333d0594c66 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml @@ -0,0 +1,798 @@ +openapi: 3.0.1 +info: + title: SLOs + description: OpenAPI schema for SLOs endpoints + version: '0.1' + contact: + name: Actionable Observability Team + license: + name: Elastic License 2.0 + url: https://www.elastic.co/licensing/elastic-license +tags: + - name: slos + description: SLO APIs enable you to define, manage and track service-level objectives +servers: + - url: http://localhost:5601 + description: local +paths: + /s/{spaceId}/api/observability/slos: + post: + summary: Creates an SLO. + operationId: createSlo + description: | + You must have `all` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/create_slo_request' + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '#/components/schemas/create_slo_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + servers: + - url: https://localhost:5601 + get: + summary: Retrieves a paginated list of SLOs + operationId: findSlos + description: | + You must have the `read` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + - name: name + in: query + description: Filter by name + schema: + type: string + example: awesome-service + - name: indicatorTypes + in: query + description: Filter by indicator type + schema: + type: array + items: + type: string + example: + - sli.kql.custom + - name: page + in: query + description: The page number to return + schema: + type: integer + default: 1 + example: 1 + - name: perPage + in: query + description: The number of SLOs to return per page + schema: + type: integer + default: 25 + example: 20 + - name: sortBy + in: query + description: Sort by field + schema: + type: string + enum: + - name + - indicatorType + default: name + example: name + - name: sortDirection + in: query + description: Sort order + schema: + type: string + enum: + - asc + - desc + default: asc + example: asc + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '#/components/schemas/find_slo_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + /s/{spaceId}/api/observability/slos/{sloId}: + get: + summary: Retrieves a SLO + operationId: getSlo + description: | + You must have the `read` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + - $ref: '#/components/parameters/slo_id' + responses: + '200': + description: Succesful request + content: + application/json: + schema: + $ref: '#/components/schemas/slo_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + put: + summary: Updates an SLO + operationId: updateSlo + description: | + You must have the `write` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + - $ref: '#/components/parameters/slo_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/update_slo_request' + responses: + '200': + description: Succesful request + content: + application/json: + schema: + $ref: '#/components/schemas/slo_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + delete: + summary: Deletes an SLO + operationId: deleteSlo + description: | + You must have the `write` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + - $ref: '#/components/parameters/slo_id' + responses: + '204': + description: Succesful request + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + /s/{spaceId}/api/observability/slos/{sloId}/enable: + post: + summary: Enables an SLO + operationId: enableSlo + description: | + You must have the `write` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + - $ref: '#/components/parameters/slo_id' + responses: + '204': + description: Succesful request + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + /s/{spaceId}/api/observability/slos/{sloId}/disable: + post: + summary: Disables an SLO + operationId: disableSlo + description: | + You must have the `write` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + - $ref: '#/components/parameters/slo_id' + responses: + '200': + description: Succesful request + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + /s/{spaceId}/internal/observability/slos/_historical_summary: + post: + summary: Retrieves the historical summary for a list of SLOs + operationId: historicalSummary + description: | + You must have the `read` privileges for the **SLOs** feature in the **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/historical_summary_request' + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '#/components/schemas/historical_summary_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/4xx_response' +components: + securitySchemes: + basicAuth: + type: http + scheme: basic + apiKeyAuth: + type: apiKey + in: header + name: ApiKey + parameters: + kbn_xsrf: + schema: + type: string + in: header + name: kbn-xsrf + description: Cross-site request forgery protection + required: true + space_id: + in: path + name: spaceId + description: An identifier for the space. If `/s/` and the identifier are omitted from the path, the default space is used. + required: true + schema: + type: string + example: default + slo_id: + in: path + name: sloId + description: An identifier for the slo. + required: true + schema: + type: string + example: 9c235211-6834-11ea-a78c-6feb38a34414 + schemas: + indicator_properties_custom_kql: + title: Custom KQL indicator type definition + required: + - type + - params + description: Defines properties for a custom KQL indicator type + type: object + properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - index + properties: + index: + description: The index or index pattern to use + type: string + example: my-service-* + filter: + description: the KQL query to filter the documents with. + type: string + example: 'field.environment : "production" and service.name : "my-service"' + good: + description: the KQL query used to define the good events. + type: string + example: 'request.latency <= 150 and request.status_code : "2xx"' + total: + description: the KQL query used to define all events. + type: string + example: '' + type: + description: The type of indicator. + type: string + example: sli.kql.custom + indicator_properties_apm_availability: + title: APM availability indicator type definition + required: + - type + - params + description: Defines properties for the APM availability indicator type + type: object + properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - service + - environment + - transactionType + - transactionName + properties: + service: + description: The APM service name + type: string + example: o11y-app + environment: + description: The APM service environment or "*" + type: string + example: production + transactionType: + description: The APM transaction type or "*" + type: string + example: request + transactionName: + description: The APM transaction name or "*" + type: string + example: GET /my/api + goodStatusCodes: + description: The status codes considered as good events. Default to 2xx, 3xx and 4xx + type: array + items: + type: string + example: + - 2xx + - 3xx + - 4xx + filter: + description: KQL query used for filtering the data + type: string + example: 'service.foo : "bar"' + index: + description: The index used by APM metrics + type: string + example: metrics-apm*,apm* + type: + description: The type of indicator. + type: string + example: sli.apm.transactionDuration + indicator_properties_apm_latency: + title: APM latency indicator type definition + required: + - type + - params + description: Defines properties for the APM latency indicator type + type: object + properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - service + - environment + - transactionType + - transactionName + properties: + service: + description: The APM service name + type: string + example: o11y-app + environment: + description: The APM service environment or "*" + type: string + example: production + transactionType: + description: The APM transaction type or "*" + type: string + example: request + transactionName: + description: The APM transaction name or "*" + type: string + example: GET /my/api + filter: + description: KQL query used for filtering the data + type: string + example: 'service.foo : "bar"' + index: + description: The index used by APM metrics + type: string + example: metrics-apm*,apm* + type: + description: The type of indicator. + type: string + example: sli.apm.transactionDuration + time_window_rolling: + title: Rolling time window definition + required: + - duration + - isRolling + description: Defines properties for rolling time window + type: object + properties: + duration: + description: the duration formatted as {duration}{unit} + type: string + example: 28d + isRolling: + description: Indicates a rolling time window + type: boolean + example: true + time_window_calendar_aligned: + title: Calendar aligned time window definition + required: + - duration + - calendar + description: Defines properties for calendar aligned time window + type: object + properties: + duration: + description: the duration formatted as {duration}{unit} + type: string + example: 1M + calendar: + description: Defines the calendar start date + type: object + properties: + startTime: + description: The start date to use. + type: string + example: '2022-01-01T08:00:00.000Z' + budgeting_method: + title: Budgeting method + type: string + description: The budgeting method to use + enum: + - occurrences + - timeslices + example: occurrences + objective: + title: Objective definition + required: + - target + description: Defines properties for objective + type: object + properties: + target: + description: the target objective between 0 and 1 excluded + type: number + example: 0.99 + timeslicesTarget: + description: the target objective for each slice when using a timeslices budgeting method + type: number + example: 0.995 + timeslicesWindow: + description: the duration of each slice when using a timeslices budgeting method, as {duraton}{unit} + type: string + example: 5m + settings: + title: Settings definition + description: Defines properties for settings. + type: object + properties: + timestampField: + description: | + The timestamp field used in the source indice. Particularly useful for custom kql indicator type, when the index does not use the default '@timestamp' field + type: string + example: timestamp + syncDelay: + description: The synch delay to apply to the transform. Default 1m + type: string + example: 5m + frequency: + description: Configure how often the transform runs, default 1m + type: string + example: 5m + error_budget: + title: Error budget definition + type: object + properties: + initial: + type: number + description: The initial error budget, as 1 - objective + example: 0.02 + consumed: + type: number + description: The error budget consummed, as a percentage of the initial value. + example: 0.8 + remaining: + type: number + description: The error budget remaining, as a percentage of the initial value. + example: 0.2 + isEstimated: + type: boolean + description: Only for SLO defined with occurrences budgeting method and calendar aligned time window. + example: true + summary: + title: Summary definition + type: object + properties: + status: + type: string + enum: + - NO_DATA + - HEALTHY + - DEGRADING + - VIOLATED + example: HEALTHY + sliValue: + type: number + example: 0.9836 + errorBudget: + $ref: '#/components/schemas/error_budget' + slo_response: + title: SLO Response + type: object + properties: + id: + description: The identifier of the SLO. + type: string + example: 8853df00-ae2e-11ed-90af-09bb6422b258 + name: + description: The name of the SLO. + type: string + example: My Service SLO + description: + description: The description of the SLO. + type: string + example: My SLO description + indicator: + oneOf: + - $ref: '#/components/schemas/indicator_properties_custom_kql' + - $ref: '#/components/schemas/indicator_properties_apm_availability' + - $ref: '#/components/schemas/indicator_properties_apm_latency' + timeWindow: + oneOf: + - $ref: '#/components/schemas/time_window_rolling' + - $ref: '#/components/schemas/time_window_calendar_aligned' + budgetingMethod: + $ref: '#/components/schemas/budgeting_method' + objective: + $ref: '#/components/schemas/objective' + settings: + $ref: '#/components/schemas/settings' + revision: + description: The SLO revision + type: number + example: 2 + summary: + $ref: '#/components/schemas/summary' + enabled: + description: Indicate if the SLO is enabled + type: boolean + example: true + createdAt: + description: The creation date + type: string + example: '2023-01-12T10:03:19.000Z' + updatedAt: + description: The last update date + type: string + example: '2023-01-12T10:03:19.000Z' + find_slo_response: + title: Find SLO response + description: | + A paginated response of SLOs matching the query. + type: object + properties: + page: + type: number + example: 1 + perPage: + type: number + example: 25 + total: + type: number + example: 34 + results: + type: array + items: + $ref: '#/components/schemas/slo_response' + 4xx_response: + title: Bad response + type: object + required: + - statusCode + - error + - message + properties: + statusCode: + type: number + example: 401 + error: + type: string + example: Unauthorized + message: + type: string + example: "[security_exception\n\tRoot causes:\n\t\tsecurity_exception: unable to authenticate user [elastics] for REST request [/_security/_authenticate]]: unable to authenticate user [elastics] for REST request [/_security/_authenticate]" + create_slo_request: + title: Create SLO request + description: | + The create SLO API request body varies depending on the type of indicator, time window and budgeting method. + type: object + required: + - name + - description + - indicator + - timeWindow + - budgetingMethod + - objective + properties: + name: + description: A name for the SLO. + type: string + description: + description: A description for the SLO. + type: string + indicator: + oneOf: + - $ref: '#/components/schemas/indicator_properties_custom_kql' + - $ref: '#/components/schemas/indicator_properties_apm_availability' + - $ref: '#/components/schemas/indicator_properties_apm_latency' + timeWindow: + oneOf: + - $ref: '#/components/schemas/time_window_rolling' + - $ref: '#/components/schemas/time_window_calendar_aligned' + budgetingMethod: + $ref: '#/components/schemas/budgeting_method' + objective: + $ref: '#/components/schemas/objective' + settings: + $ref: '#/components/schemas/settings' + create_slo_response: + title: Create SLO response + type: object + required: + - id + properties: + id: + type: string + example: 8853df00-ae2e-11ed-90af-09bb6422b258 + update_slo_request: + title: Update SLO request + description: | + The update SLO API request body varies depending on the type of indicator, time window and budgeting method. Partial update is handled. + type: object + properties: + name: + description: A name for the SLO. + type: string + description: + description: A description for the SLO. + type: string + indicator: + oneOf: + - $ref: '#/components/schemas/indicator_properties_custom_kql' + - $ref: '#/components/schemas/indicator_properties_apm_availability' + - $ref: '#/components/schemas/indicator_properties_apm_latency' + timeWindow: + oneOf: + - $ref: '#/components/schemas/time_window_rolling' + - $ref: '#/components/schemas/time_window_calendar_aligned' + budgetingMethod: + $ref: '#/components/schemas/budgeting_method' + objective: + $ref: '#/components/schemas/objective' + settings: + $ref: '#/components/schemas/settings' + historical_summary_request: + title: Historical summary request + type: object + required: + - sloIds + properties: + sloIds: + description: The list of SLO identifiers to get the historical summary for + type: array + items: + type: string + example: 8853df00-ae2e-11ed-90af-09bb6422b258 + historical_summary_response: + title: Historical summary response + type: object + additionalProperties: + type: array + items: + type: object + properties: + date: + type: string + example: '2022-01-01T00:00:00.000Z' + status: + type: string + enum: + - NO_DATA + - HEALTHY + - DEGRADING + - VIOLATED + example: HEALTHY + sliValue: + type: number + example: 0.9836 + errorBudget: + $ref: '#/components/schemas/error_budget' +security: + - basicAuth: [] + - apiKeyAuth: [] diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/README.md b/x-pack/plugins/observability/docs/openapi/slo/components/README.md new file mode 100644 index 0000000000000..0841562a33150 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/README.md @@ -0,0 +1,7 @@ +Reusable components +=========== + + - `examples` - reusable [Example objects](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#exampleObject) + - `headers` - reusable [Header objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#headerObject) + - `parameters` - reusable [Parameter objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject) + - `schemas` - reusable [Schema objects](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#schemaObject) diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/headers/kbn_xsrf.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/headers/kbn_xsrf.yaml new file mode 100644 index 0000000000000..fe0402a43aa03 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/headers/kbn_xsrf.yaml @@ -0,0 +1,6 @@ +schema: + type: string +in: header +name: kbn-xsrf +description: Cross-site request forgery protection +required: true diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/parameters/slo_id.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/parameters/slo_id.yaml new file mode 100644 index 0000000000000..9b687ee1b0b05 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/parameters/slo_id.yaml @@ -0,0 +1,7 @@ +in: path +name: sloId +description: An identifier for the slo. +required: true +schema: + type: string + example: 9c235211-6834-11ea-a78c-6feb38a34414 diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/parameters/space_id.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/parameters/space_id.yaml new file mode 100644 index 0000000000000..0a9fba457e3e7 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/parameters/space_id.yaml @@ -0,0 +1,7 @@ +in: path +name: spaceId +description: An identifier for the space. If `/s/` and the identifier are omitted from the path, the default space is used. +required: true +schema: + type: string + example: default diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/4xx_response.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/4xx_response.yaml new file mode 100644 index 0000000000000..caf2d3a50d53a --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/4xx_response.yaml @@ -0,0 +1,16 @@ +title: Bad response +type: object +required: + - statusCode + - error + - message +properties: + statusCode: + type: number + example: 401 + error: + type: string + example: Unauthorized + message: + type: string + example: "[security_exception\n\tRoot causes:\n\t\tsecurity_exception: unable to authenticate user [elastics] for REST request [/_security/_authenticate]]: unable to authenticate user [elastics] for REST request [/_security/_authenticate]" diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/budgeting_method.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/budgeting_method.yaml new file mode 100644 index 0000000000000..8b3957ddfa1cb --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/budgeting_method.yaml @@ -0,0 +1,7 @@ +title: Budgeting method +type: string +description: The budgeting method to use +enum: + - occurrences + - timeslices +example: occurrences \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml new file mode 100644 index 0000000000000..e4321039189e1 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml @@ -0,0 +1,33 @@ +title: Create SLO request +description: > + The create SLO API request body varies depending on the type of indicator, time window and budgeting method. +type: object +required: + - name + - description + - indicator + - timeWindow + - budgetingMethod + - objective +properties: + name: + description: A name for the SLO. + type: string + description: + description: A description for the SLO. + type: string + indicator: + oneOf: + - $ref: 'indicator_properties_custom_kql.yaml' + - $ref: 'indicator_properties_apm_availability.yaml' + - $ref: 'indicator_properties_apm_latency.yaml' + timeWindow: + oneOf: + - $ref: 'time_window_rolling.yaml' + - $ref: 'time_window_calendar_aligned.yaml' + budgetingMethod: + $ref: 'budgeting_method.yaml' + objective: + $ref: 'objective.yaml' + settings: + $ref: 'settings.yaml' diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_response.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_response.yaml new file mode 100644 index 0000000000000..ce01f2cae39b8 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_response.yaml @@ -0,0 +1,8 @@ +title: Create SLO response +type: object +required: + - id +properties: + id: + type: string + example: 8853df00-ae2e-11ed-90af-09bb6422b258 diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/error_budget.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/error_budget.yaml new file mode 100644 index 0000000000000..67977a2c44931 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/error_budget.yaml @@ -0,0 +1,19 @@ +title: Error budget definition +type: object +properties: + initial: + type: number + description: The initial error budget, as 1 - objective + example: 0.02 + consumed: + type: number + description: The error budget consummed, as a percentage of the initial value. + example: 0.80 + remaining: + type: number + description: The error budget remaining, as a percentage of the initial value. + example: 0.20 + isEstimated: + type: boolean + description: Only for SLO defined with occurrences budgeting method and calendar aligned time window. + example: true \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/find_slo_response.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/find_slo_response.yaml new file mode 100644 index 0000000000000..36a701efa34f4 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/find_slo_response.yaml @@ -0,0 +1,18 @@ +title: Find SLO response +description: > + A paginated response of SLOs matching the query. +type: object +properties: + page: + type: number + example: 1 + perPage: + type: number + example: 25 + total: + type: number + example: 34 + results: + type: array + items: + $ref: 'slo_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/historical_summary_request.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/historical_summary_request.yaml new file mode 100644 index 0000000000000..737a5b83f03f9 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/historical_summary_request.yaml @@ -0,0 +1,12 @@ +title: Historical summary request +type: object +required: + - sloIds +properties: + sloIds: + description: The list of SLO identifiers to get the historical summary for + type: array + items: + type: string + example: 8853df00-ae2e-11ed-90af-09bb6422b258 + \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/historical_summary_response.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/historical_summary_response.yaml new file mode 100644 index 0000000000000..923d6acbeaa93 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/historical_summary_response.yaml @@ -0,0 +1,23 @@ +title: Historical summary response +type: object +additionalProperties: + type: array + items: + type: object + properties: + date: + type: string + example: "2022-01-01T00:00:00.000Z" + status: + type: string + enum: + - NO_DATA + - HEALTHY + - DEGRADING + - VIOLATED + example: "HEALTHY" + sliValue: + type: number + example: 0.9836 + errorBudget: + $ref: 'error_budget.yaml' \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_apm_availability.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_apm_availability.yaml new file mode 100644 index 0000000000000..29eca24b8df3b --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_apm_availability.yaml @@ -0,0 +1,54 @@ +title: APM availability indicator type definition +required: + - type + - params +description: Defines properties for the APM availability indicator type +type: object +properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - service + - environment + - transactionType + - transactionName + properties: + service: + description: The APM service name + type: string + example: o11y-app + environment: + description: The APM service environment or "*" + type: string + example: production + transactionType: + description: The APM transaction type or "*" + type: string + example: request + transactionName: + description: The APM transaction name or "*" + type: string + example: GET /my/api + goodStatusCodes: + description: The status codes considered as good events. Default to 2xx, 3xx and 4xx + type: array + items: + type: string + example: + - "2xx" + - "3xx" + - "4xx" + filter: + description: KQL query used for filtering the data + type: string + example: 'service.foo : "bar"' + index: + description: The index used by APM metrics + type: string + example: metrics-apm*,apm* + type: + description: The type of indicator. + type: string + example: sli.apm.transactionDuration diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_apm_latency.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_apm_latency.yaml new file mode 100644 index 0000000000000..7ec3bf40871d8 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_apm_latency.yaml @@ -0,0 +1,45 @@ +title: APM latency indicator type definition +required: + - type + - params +description: Defines properties for the APM latency indicator type +type: object +properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - service + - environment + - transactionType + - transactionName + properties: + service: + description: The APM service name + type: string + example: o11y-app + environment: + description: The APM service environment or "*" + type: string + example: production + transactionType: + description: The APM transaction type or "*" + type: string + example: request + transactionName: + description: The APM transaction name or "*" + type: string + example: GET /my/api + filter: + description: KQL query used for filtering the data + type: string + example: 'service.foo : "bar"' + index: + description: The index used by APM metrics + type: string + example: metrics-apm*,apm* + type: + description: The type of indicator. + type: string + example: sli.apm.transactionDuration diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_custom_kql.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_custom_kql.yaml new file mode 100644 index 0000000000000..e5ef6cddf858a --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_custom_kql.yaml @@ -0,0 +1,34 @@ +title: Custom KQL indicator type definition +required: + - type + - params +description: Defines properties for a custom KQL indicator type +type: object +properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - index + properties: + index: + description: The index or index pattern to use + type: string + example: my-service-* + filter: + description: the KQL query to filter the documents with. + type: string + example: 'field.environment : "production" and service.name : "my-service"' + good: + description: the KQL query used to define the good events. + type: string + example: 'request.latency <= 150 and request.status_code : "2xx"' + total: + description: the KQL query used to define all events. + type: string + example: '' + type: + description: The type of indicator. + type: string + example: sli.kql.custom diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/objective.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/objective.yaml new file mode 100644 index 0000000000000..b64c3cc0dd15a --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/objective.yaml @@ -0,0 +1,18 @@ +title: Objective definition +required: + - target +description: Defines properties for objective +type: object +properties: + target: + description: the target objective between 0 and 1 excluded + type: number + example: 0.99 + timeslicesTarget: + description: the target objective for each slice when using a timeslices budgeting method + type: number + example: 0.995 + timeslicesWindow: + description: the duration of each slice when using a timeslices budgeting method, as {duraton}{unit} + type: string + example: 5m diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/settings.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/settings.yaml new file mode 100644 index 0000000000000..27459b205d981 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/settings.yaml @@ -0,0 +1,18 @@ +title: Settings definition +description: Defines properties for settings. +type: object +properties: + timestampField: + description: > + The timestamp field used in the source indice. Particularly useful for custom kql indicator type, when the index + does not use the default '@timestamp' field + type: string + example: timestamp + syncDelay: + description: The synch delay to apply to the transform. Default 1m + type: string + example: 5m + frequency: + description: Configure how often the transform runs, default 1m + type: string + example: 5m diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml new file mode 100644 index 0000000000000..ffd0e23f872d5 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml @@ -0,0 +1,48 @@ +title: SLO Response +type: object +properties: + id: + description: The identifier of the SLO. + type: string + example: 8853df00-ae2e-11ed-90af-09bb6422b258 + name: + description: The name of the SLO. + type: string + example: My Service SLO + description: + description: The description of the SLO. + type: string + example: My SLO description + indicator: + oneOf: + - $ref: 'indicator_properties_custom_kql.yaml' + - $ref: 'indicator_properties_apm_availability.yaml' + - $ref: 'indicator_properties_apm_latency.yaml' + timeWindow: + oneOf: + - $ref: 'time_window_rolling.yaml' + - $ref: 'time_window_calendar_aligned.yaml' + budgetingMethod: + $ref: 'budgeting_method.yaml' + objective: + $ref: 'objective.yaml' + settings: + $ref: 'settings.yaml' + revision: + description: The SLO revision + type: number + example: 2 + summary: + $ref: 'summary.yaml' + enabled: + description: Indicate if the SLO is enabled + type: boolean + example: true + createdAt: + description: The creation date + type: string + example: "2023-01-12T10:03:19.000Z" + updatedAt: + description: The last update date + type: string + example: "2023-01-12T10:03:19.000Z" \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/summary.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/summary.yaml new file mode 100644 index 0000000000000..67662c222fae0 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/summary.yaml @@ -0,0 +1,16 @@ +title: Summary definition +type: object +properties: + status: + type: string + enum: + - NO_DATA + - HEALTHY + - DEGRADING + - VIOLATED + example: "HEALTHY" + sliValue: + type: number + example: 0.9836 + errorBudget: + $ref: 'error_budget.yaml' \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/time_window_calendar_aligned.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/time_window_calendar_aligned.yaml new file mode 100644 index 0000000000000..4c494e97110c9 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/time_window_calendar_aligned.yaml @@ -0,0 +1,19 @@ +title: Calendar aligned time window definition +required: + - duration + - calendar +description: Defines properties for calendar aligned time window +type: object +properties: + duration: + description: the duration formatted as {duration}{unit} + type: string + example: 1M + calendar: + description: Defines the calendar start date + type: object + properties: + startTime: + description: The start date to use. + type: string + example: "2022-01-01T08:00:00.000Z" diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/time_window_rolling.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/time_window_rolling.yaml new file mode 100644 index 0000000000000..9ee0060101e67 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/time_window_rolling.yaml @@ -0,0 +1,15 @@ +title: Rolling time window definition +required: + - duration + - isRolling +description: Defines properties for rolling time window +type: object +properties: + duration: + description: the duration formatted as {duration}{unit} + type: string + example: 28d + isRolling: + description: Indicates a rolling time window + type: boolean + example: true diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml new file mode 100644 index 0000000000000..19c04d62f9b82 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml @@ -0,0 +1,27 @@ +title: Update SLO request +description: > + The update SLO API request body varies depending on the type of indicator, time window and budgeting method. + Partial update is handled. +type: object +properties: + name: + description: A name for the SLO. + type: string + description: + description: A description for the SLO. + type: string + indicator: + oneOf: + - $ref: 'indicator_properties_custom_kql.yaml' + - $ref: 'indicator_properties_apm_availability.yaml' + - $ref: 'indicator_properties_apm_latency.yaml' + timeWindow: + oneOf: + - $ref: 'time_window_rolling.yaml' + - $ref: 'time_window_calendar_aligned.yaml' + budgetingMethod: + $ref: 'budgeting_method.yaml' + objective: + $ref: 'objective.yaml' + settings: + $ref: 'settings.yaml' diff --git a/x-pack/plugins/observability/docs/openapi/slo/entrypoint.yaml b/x-pack/plugins/observability/docs/openapi/slo/entrypoint.yaml new file mode 100644 index 0000000000000..f0e5812ed7688 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/entrypoint.yaml @@ -0,0 +1,39 @@ +openapi: 3.0.1 +info: + title: SLOs + description: OpenAPI schema for SLOs endpoints + version: '0.1' + contact: + name: Actionable Observability Team + license: + name: Elastic License 2.0 + url: https://www.elastic.co/licensing/elastic-license +tags: + - name: slos + description: SLO APIs enable you to define, manage and track service-level objectives +servers: + - url: 'http://localhost:5601' + description: local +paths: + '/s/{spaceId}/api/observability/slos': + $ref: 'paths/s@{spaceid}@api@slos.yaml' + '/s/{spaceId}/api/observability/slos/{sloId}': + $ref: 'paths/s@{spaceid}@api@slos@{sloid}.yaml' + '/s/{spaceId}/api/observability/slos/{sloId}/enable': + $ref: 'paths/s@{spaceid}@api@slos@{sloid}@{enable}.yaml' + '/s/{spaceId}/api/observability/slos/{sloId}/disable': + $ref: 'paths/s@{spaceid}@api@slos@{sloid}@{disable}.yaml' + '/s/{spaceId}/internal/observability/slos/_historical_summary': + $ref: 'paths/s@{spaceid}@api@slos@_historical_summary.yaml' +components: + securitySchemes: + basicAuth: + type: http + scheme: basic + apiKeyAuth: + type: apiKey + in: header + name: ApiKey +security: + - basicAuth: [] + - apiKeyAuth: [] diff --git a/x-pack/plugins/observability/docs/openapi/slo/paths/README.md b/x-pack/plugins/observability/docs/openapi/slo/paths/README.md new file mode 100644 index 0000000000000..b7818c8474fc8 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/paths/README.md @@ -0,0 +1,10 @@ +Paths +===== + +Each path definition for which there is a specification exists within this folder. + +These files currently use the following conventions: + +* path separator token (e.g. `@`) is included in the file name +* path parameter (e.g. `{example}`) is included in the file name +* there is one file per path; each file can contain multiple operations diff --git a/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos.yaml b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos.yaml new file mode 100644 index 0000000000000..76ac5912056f1 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos.yaml @@ -0,0 +1,113 @@ +post: + summary: Creates an SLO. + operationId: createSlo + description: > + You must have `all` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/create_slo_request.yaml' + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '../components/schemas/create_slo_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + servers: + - url: https://localhost:5601 + +get: + summary: Retrieves a paginated list of SLOs + operationId: findSlos + description: > + You must have the `read` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + - name: name + in: query + description: Filter by name + schema: + type: string + example: awesome-service + - name: indicatorTypes + in: query + description: Filter by indicator type + schema: + type: array + items: + type: string + example: ["sli.kql.custom"] + - name: page + in: query + description: The page number to return + schema: + type: integer + default: 1 + example: 1 + - name: perPage + in: query + description: The number of SLOs to return per page + schema: + type: integer + default: 25 + example: 20 + - name: sortBy + in: query + description: Sort by field + schema: + type: string + enum: [name, indicatorType] + default: name + example: name + - name: sortDirection + in: query + description: Sort order + schema: + type: string + enum: [asc, desc] + default: asc + example: asc + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '../components/schemas/find_slo_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@_historical_summary.yaml b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@_historical_summary.yaml new file mode 100644 index 0000000000000..59d9cedada877 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@_historical_summary.yaml @@ -0,0 +1,36 @@ +post: + summary: Retrieves the historical summary for a list of SLOs + operationId: historicalSummary + description: > + You must have the `read` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/historical_summary_request.yaml' + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '../components/schemas/historical_summary_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' diff --git a/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}.yaml b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}.yaml new file mode 100644 index 0000000000000..c4324108f6d6b --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}.yaml @@ -0,0 +1,97 @@ +get: + summary: Retrieves a SLO + operationId: getSlo + description: > + You must have the `read` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + - $ref: ../components/parameters/slo_id.yaml + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '../components/schemas/slo_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + +put: + summary: Updates an SLO + operationId: updateSlo + description: > + You must have the `write` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + - $ref: ../components/parameters/slo_id.yaml + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/update_slo_request.yaml' + responses: + '200': + description: Successful request + content: + application/json: + schema: + $ref: '../components/schemas/slo_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + +delete: + summary: Deletes an SLO + operationId: deleteSlo + description: > + You must have the `write` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + - $ref: ../components/parameters/slo_id.yaml + responses: + '204': + description: Successful request + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' diff --git a/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}@{disable}.yaml b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}@{disable}.yaml new file mode 100644 index 0000000000000..a35878b62b0bc --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}@{disable}.yaml @@ -0,0 +1,27 @@ +post: + summary: Disables an SLO + operationId: disableSlo + description: > + You must have the `write` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + - $ref: ../components/parameters/slo_id.yaml + responses: + '200': + description: Successful request + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' diff --git a/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}@{enable}.yaml b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}@{enable}.yaml new file mode 100644 index 0000000000000..bd07103f52706 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/paths/s@{spaceid}@api@slos@{sloid}@{enable}.yaml @@ -0,0 +1,27 @@ +post: + summary: Enables an SLO + operationId: enableSlo + description: > + You must have the `write` privileges for the **SLOs** feature in the + **Observability** section of the Kibana feature privileges. + tags: + - slos + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: ../components/parameters/space_id.yaml + - $ref: ../components/parameters/slo_id.yaml + responses: + '204': + description: Successful request + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' + '401': + description: Unauthorized response + content: + application/json: + schema: + $ref: '../components/schemas/4xx_response.yaml' diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_apm_suggestions.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_apm_suggestions.ts index 4edea41bdc1fb..d14143fe9ae0e 100644 --- a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_apm_suggestions.ts +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_apm_suggestions.ts @@ -10,12 +10,12 @@ import { Params, UseFetchApmSuggestions } from '../use_fetch_apm_suggestions'; export const useFetchApmSuggestions = ({ fieldName, search = '', + serviceName = '', }: Params): UseFetchApmSuggestions => { return { isLoading: false, isError: false, isSuccess: true, suggestions: ['apm-suggestion-1', 'apm-suggestion-2', 'apm-suggestion-3'], - refetch: function () {} as UseFetchApmSuggestions['refetch'], }; }; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_indices.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_indices.ts new file mode 100644 index 0000000000000..702573fa570dd --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_indices.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useQuery } from '@tanstack/react-query'; + +import { useKibana } from '../../utils/kibana_react'; + +type ApmIndex = string; + +export interface UseFetchApmIndex { + data: ApmIndex; + isLoading: boolean; + isSuccess: boolean; + isError: boolean; +} + +interface ApiResponse { + apmIndexSettings: Array<{ + configurationName: string; + defaultValue: string; + savedValue?: string; + }>; +} + +export function useFetchApmIndex(): UseFetchApmIndex { + const { http } = useKibana().services; + + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: ['fetchApmIndices'], + queryFn: async ({ signal }) => { + try { + const response = await http.get('/internal/apm/settings/apm-index-settings', { + signal, + }); + + const metricSettings = response.apmIndexSettings.find( + (settings) => settings.configurationName === 'metric' + ); + + let index = ''; + if (!!metricSettings) { + index = metricSettings.savedValue ?? metricSettings.defaultValue; + } + + return index; + } catch (error) { + // ignore error + } + }, + refetchOnWindowFocus: false, + }); + + return { + data: isInitialLoading ? '' : data ?? '', + isLoading: isInitialLoading || isLoading || isRefetching, + isSuccess, + isError, + }; +} diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts index 72350d9227867..cc7bdb1193d63 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts @@ -5,13 +5,9 @@ * 2.0. */ -import { - QueryObserverResult, - RefetchOptions, - RefetchQueryFilters, - useQuery, -} from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import moment from 'moment'; + import { useKibana } from '../../utils/kibana_react'; export type Suggestion = string; @@ -20,14 +16,12 @@ export interface UseFetchApmSuggestions { isLoading: boolean; isSuccess: boolean; isError: boolean; - refetch: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise>; } export interface Params { fieldName: string; - search: string; + search?: string; + serviceName?: string; } interface ApiResponse { @@ -36,37 +30,40 @@ interface ApiResponse { const EMPTY_RESPONSE: ApiResponse = { terms: [] }; -export function useFetchApmSuggestions({ fieldName, search = '' }: Params): UseFetchApmSuggestions { +export function useFetchApmSuggestions({ + fieldName, + search = '', + serviceName = '', +}: Params): UseFetchApmSuggestions { const { http } = useKibana().services; - const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( - { - queryKey: ['fetchApmSuggestions', fieldName, search], - queryFn: async ({ signal }) => { - try { - const { terms = [] } = await http.get('/internal/apm/suggestions', { - query: { - fieldName, - start: moment().subtract(2, 'days').toISOString(), - end: moment().toISOString(), - fieldValue: search, - }, - signal, - }); + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: ['fetchApmSuggestions', fieldName, search, serviceName], + queryFn: async ({ signal }) => { + try { + const { terms = [] } = await http.get('/internal/apm/suggestions', { + query: { + fieldName, + start: moment().subtract(2, 'days').toISOString(), + end: moment().toISOString(), + fieldValue: search, + ...(!!serviceName && { serviceName }), + }, + signal, + }); - return terms; - } catch (error) { - // ignore error for retrieving slos - } - }, - } - ); + return terms; + } catch (error) { + // ignore error + } + }, + refetchOnWindowFocus: false, + }); return { suggestions: isInitialLoading ? EMPTY_RESPONSE.terms : data ?? EMPTY_RESPONSE.terms, isLoading: isInitialLoading || isLoading || isRefetching, isSuccess, isError, - refetch, }; } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts index e91269d4b1d9b..b706add340801 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts @@ -43,6 +43,7 @@ export function useFetchSloDetails(sloId: string): UseFetchSloDetailsResponse { } }, enabled: Boolean(sloId), + refetchOnWindowFocus: false, } ); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.stories.tsx index 9f1ca20c3411f..c3c506eb484eb 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.stories.tsx @@ -10,10 +10,7 @@ import { ComponentStory } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; import { KibanaReactStorybookDecorator } from '../../../../utils/kibana_react.storybook_decorator'; -import { - ApmAvailabilityIndicatorTypeForm as Component, - Props, -} from './apm_availability_indicator_type_form'; +import { ApmAvailabilityIndicatorTypeForm as Component } from './apm_availability_indicator_type_form'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../../constants'; export default { @@ -22,11 +19,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: Props) => { +const Template: ComponentStory = () => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx index bac23feb17b85..c24bf74dc6346 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption, @@ -13,17 +13,20 @@ import { EuiFlexItem, EuiFormLabel, } from '@elastic/eui'; -import { Control, Controller } from 'react-hook-form'; +import { Controller, useFormContext } from 'react-hook-form'; import { i18n } from '@kbn/i18n'; import type { CreateSLOInput } from '@kbn/slo-schema'; +import { useFetchApmIndex } from '../../../../hooks/slo/use_fetch_apm_indices'; import { FieldSelector } from '../common/field_selector'; -export interface Props { - control: Control; -} +export function ApmAvailabilityIndicatorTypeForm() { + const { control, setValue } = useFormContext(); + const { data: apmIndex } = useFetchApmIndex(); + useEffect(() => { + setValue('indicator.params.index', apmIndex); + }, [apmIndex, setValue]); -export function ApmAvailabilityIndicatorTypeForm({ control }: Props) { return ( @@ -40,7 +43,6 @@ export function ApmAvailabilityIndicatorTypeForm({ control }: Props) { )} fieldName="service.name" name="indicator.params.service" - control={control} dataTestSubj="apmAvailabilityServiceSelector" /> @@ -79,7 +80,6 @@ export function ApmAvailabilityIndicatorTypeForm({ control }: Props) { )} fieldName="transaction.type" name="indicator.params.transactionType" - control={control} dataTestSubj="apmAvailabilityTransactionTypeSelector" /> @@ -131,10 +130,14 @@ export function ApmAvailabilityIndicatorTypeForm({ control }: Props) { } )} isInvalid={!!fieldState.error} - options={generateStatusCodeOptions()} + options={generateStatusCodeOptions(['2xx', '3xx', '4xx', '5xx'])} selectedOptions={generateStatusCodeOptions(field.value)} onChange={(selected: EuiComboBoxOptionOption[]) => { - field.onChange(selected.map((opts) => opts.value)); + if (selected.length) { + return field.onChange(selected.map((opts) => opts.value)); + } + + field.onChange([]); }} isClearable={true} data-test-subj="sloEditApmAvailabilityGoodStatusCodesSelector" @@ -148,7 +151,7 @@ export function ApmAvailabilityIndicatorTypeForm({ control }: Props) { ); } -function generateStatusCodeOptions(codes: string[] = ['2xx', '3xx', '4xx', '5xx']) { +function generateStatusCodeOptions(codes: string[] = []) { return codes.map((code) => ({ label: code, value: code, diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.stories.tsx index 7b98c21b6e5e4..3ca02641f9bfa 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.stories.tsx @@ -10,7 +10,7 @@ import { ComponentStory } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; import { KibanaReactStorybookDecorator } from '../../../../utils/kibana_react.storybook_decorator'; -import { ApmLatencyIndicatorTypeForm as Component, Props } from './apm_latency_indicator_type_form'; +import { ApmLatencyIndicatorTypeForm as Component } from './apm_latency_indicator_type_form'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../../constants'; export default { @@ -19,11 +19,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: Props) => { +const Template: ComponentStory = () => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx index a8515d157bbcf..4dcf095571c4a 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx @@ -5,19 +5,22 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiFormLabel } from '@elastic/eui'; -import { Control, Controller } from 'react-hook-form'; +import { Controller, useFormContext } from 'react-hook-form'; import { i18n } from '@kbn/i18n'; import type { CreateSLOInput } from '@kbn/slo-schema'; +import { useFetchApmIndex } from '../../../../hooks/slo/use_fetch_apm_indices'; import { FieldSelector } from '../common/field_selector'; -export interface Props { - control: Control; -} +export function ApmLatencyIndicatorTypeForm() { + const { control, setValue } = useFormContext(); + const { data: apmIndex } = useFetchApmIndex(); + useEffect(() => { + setValue('indicator.params.index', apmIndex); + }, [apmIndex, setValue]); -export function ApmLatencyIndicatorTypeForm({ control }: Props) { return ( @@ -34,7 +37,6 @@ export function ApmLatencyIndicatorTypeForm({ control }: Props) { )} fieldName="service.name" name="indicator.params.service" - control={control} dataTestSubj="apmLatencyServiceSelector" /> @@ -67,7 +68,6 @@ export function ApmLatencyIndicatorTypeForm({ control }: Props) { )} fieldName="transaction.type" name="indicator.params.transactionType" - control={control} dataTestSubj="apmLatencyTransactionTypeSelector" /> diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx index b20915109f2b4..748b53ca82d57 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx @@ -23,7 +23,7 @@ const Template: ComponentStory = (props: Props) => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.tsx index 665758c63008e..92dc0ba682225 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption, EuiFlexItem, EuiFormLabel } from '@elastic/eui'; -import { Control, Controller, FieldPath } from 'react-hook-form'; +import { Controller, FieldPath, useFormContext } from 'react-hook-form'; import { CreateSLOInput } from '@kbn/slo-schema'; import { i18n } from '@kbn/i18n'; import { @@ -22,7 +22,6 @@ interface Option { export interface Props { allowAllOption?: boolean; - control: Control; dataTestSubj: string; fieldName: string; label: string; @@ -32,37 +31,33 @@ export interface Props { export function FieldSelector({ allowAllOption = true, - control, dataTestSubj, fieldName, label, name, placeholder, }: Props) { + const { control, watch } = useFormContext(); + const serviceName = watch('indicator.params.service'); const [search, setSearch] = useState(''); const { suggestions, isLoading } = useFetchApmSuggestions({ fieldName, search, + serviceName, }); - const [options, setOptions] = useState([]); - useEffect(() => { - const opts = ( - allowAllOption - ? [ - { - value: '*', - label: i18n.translate('xpack.observability.slos.sloEdit.fieldSelector.all', { - defaultMessage: 'All', - }), - }, - ] - : [] - ).concat(createOptions(suggestions)); - - setOptions(opts); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [suggestions.length]); + const options = ( + allowAllOption + ? [ + { + value: '*', + label: i18n.translate('xpack.observability.slos.sloEdit.fieldSelector.all', { + defaultMessage: 'All', + }), + }, + ] + : [] + ).concat(createOptions(suggestions)); return ( @@ -81,6 +76,7 @@ export function FieldSelector({ async data-test-subj={dataTestSubj} isClearable={true} + isDisabled={name !== 'indicator.params.service' && !serviceName} isInvalid={!!fieldState.error} isLoading={isLoading} onChange={(selected: EuiComboBoxOptionOption[]) => { diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.stories.tsx index 375b133adfb43..5eb0b68070789 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.stories.tsx @@ -10,7 +10,7 @@ import { ComponentStory } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; import { KibanaReactStorybookDecorator } from '../../../../utils/kibana_react.storybook_decorator'; -import { CustomKqlIndicatorTypeForm as Component, Props } from './custom_kql_indicator_type_form'; +import { CustomKqlIndicatorTypeForm as Component } from './custom_kql_indicator_type_form'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../../constants'; export default { @@ -19,11 +19,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: Props) => { +const Template: ComponentStory = () => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx index 07b8bf4d192eb..d9c39b0715be4 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx @@ -8,18 +8,14 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Control, UseFormWatch } from 'react-hook-form'; -import type { CreateSLOInput } from '@kbn/slo-schema'; +import { useFormContext } from 'react-hook-form'; +import { CreateSLOInput } from '@kbn/slo-schema'; import { IndexSelection } from './index_selection'; import { QueryBuilder } from './query_builder'; -export interface Props { - control: Control; - watch: UseFormWatch; -} - -export function CustomKqlIndicatorTypeForm({ control, watch }: Props) { +export function CustomKqlIndicatorTypeForm() { + const { control, watch } = useFormContext(); return ( diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx index 4728d72bdec6c..01a16fe8c8220 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; -import { Controller, useForm } from 'react-hook-form'; +import { Controller, FormProvider, useForm } from 'react-hook-form'; import type { SLOWithSummaryResponse } from '@kbn/slo-schema'; import { useKibana } from '../../../utils/kibana_react'; @@ -53,11 +53,12 @@ export function SloEditForm({ slo }: Props) { notifications: { toasts }, } = useKibana().services; - const { control, watch, getFieldState, getValues, formState } = useForm({ + const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES, values: transformSloResponseToCreateSloInput(slo), mode: 'all', }); + const { control, watch, getFieldState, getValues, formState } = methods; const { isIndicatorSectionValid, isDescriptionSectionValid, isObjectiveSectionValid } = useSectionFormValidation({ @@ -122,159 +123,165 @@ export function SloEditForm({ slo }: Props) { const getIndicatorTypeForm = () => { switch (watch('indicator.type')) { case 'sli.kql.custom': - return ; + return ; case 'sli.apm.transactionDuration': - return ; + return ; case 'sli.apm.transactionErrorRate': - return ; + return ; default: return null; } }; return ( - - - } - > - - -

- {i18n.translate('xpack.observability.slos.sloEdit.definition.title', { - defaultMessage: 'Define SLI', + + + + } + > + + +

+ {i18n.translate('xpack.observability.slos.sloEdit.definition.title', { + defaultMessage: 'Define SLI', + })} +

+
+ + + + + {i18n.translate('xpack.observability.slos.sloEdit.definition.sliType', { + defaultMessage: 'SLI type', })} -

-
- - - - - {i18n.translate('xpack.observability.slos.sloEdit.definition.sliType', { - defaultMessage: 'SLI type', - })} - - - ( - - )} - /> - - - - {getIndicatorTypeForm()} - - -
-
- - - } - verticalAlign="top" - > - - -

- {i18n.translate('xpack.observability.slos.sloEdit.objectives.title', { - defaultMessage: 'Set objectives', - })} -

-
- - - - - - -
-
- - - } - > - - -

- {i18n.translate('xpack.observability.slos.sloEdit.description.title', { - defaultMessage: 'Describe SLO', - })} -

-
- - - - - - - - - - {isEditMode - ? i18n.translate('xpack.observability.slos.sloEdit.editSloButton', { - defaultMessage: 'Update SLO', - }) - : i18n.translate('xpack.observability.slos.sloEdit.createSloButton', { - defaultMessage: 'Create SLO', - })} - - - navigateToUrl(basePath.prepend(paths.observability.slos))} - > - {i18n.translate('xpack.observability.slos.sloEdit.cancelButton', { - defaultMessage: 'Cancel', - })} - - - - -
-
-
+ + + ( + + )} + /> + + + + {getIndicatorTypeForm()} + + + + + + + } + verticalAlign="top" + > + + +

+ {i18n.translate('xpack.observability.slos.sloEdit.objectives.title', { + defaultMessage: 'Set objectives', + })} +

+
+ + + + + + +
+
+ + + } + > + + +

+ {i18n.translate('xpack.observability.slos.sloEdit.description.title', { + defaultMessage: 'Describe SLO', + })} +

+
+ + + + + + + + + + {isEditMode + ? i18n.translate('xpack.observability.slos.sloEdit.editSloButton', { + defaultMessage: 'Update SLO', + }) + : i18n.translate('xpack.observability.slos.sloEdit.createSloButton', { + defaultMessage: 'Create SLO', + })} + + + navigateToUrl(basePath.prepend(paths.observability.slos))} + > + {i18n.translate('xpack.observability.slos.sloEdit.cancelButton', { + defaultMessage: 'Cancel', + })} + + + + +
+
+ + ); } diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.stories.tsx index 42b6d674b2f6d..69b765ab6a4b9 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.stories.tsx @@ -10,7 +10,7 @@ import { ComponentStory } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; -import { SloEditFormDescription as Component, Props } from './slo_edit_form_description'; +import { SloEditFormDescription as Component } from './slo_edit_form_description'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../constants'; export default { @@ -19,11 +19,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: Props) => { +const Template: ComponentStory = () => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.tsx index 15e13c53862b3..6b6780358376f 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_description.tsx @@ -15,14 +15,11 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { Control, Controller } from 'react-hook-form'; +import { Controller, useFormContext } from 'react-hook-form'; import type { CreateSLOInput } from '@kbn/slo-schema'; -export interface Props { - control: Control; -} - -export function SloEditFormDescription({ control }: Props) { +export function SloEditFormDescription() { + const { control } = useFormContext(); const sloNameId = useGeneratedHtmlId({ prefix: 'sloName' }); const descriptionId = useGeneratedHtmlId({ prefix: 'sloDescription' }); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.stories.tsx index 3540c71fc231d..edb9779f3ca7f 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.stories.tsx @@ -10,7 +10,7 @@ import { ComponentStory } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; -import { SloEditFormObjectives as Component, Props } from './slo_edit_form_objectives'; +import { SloEditFormObjectives as Component } from './slo_edit_form_objectives'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../constants'; export default { @@ -19,11 +19,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: Props) => { +const Template: ComponentStory = () => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.tsx index 0bd10e6d0fcf5..083224af18595 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives.tsx @@ -16,18 +16,14 @@ import { useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Control, Controller, UseFormWatch } from 'react-hook-form'; +import { Controller, useFormContext } from 'react-hook-form'; import type { CreateSLOInput } from '@kbn/slo-schema'; import { SloEditFormObjectivesTimeslices } from './slo_edit_form_objectives_timeslices'; import { BUDGETING_METHOD_OPTIONS, TIMEWINDOW_OPTIONS } from '../constants'; -export interface Props { - control: Control; - watch: UseFormWatch; -} - -export function SloEditFormObjectives({ control, watch }: Props) { +export function SloEditFormObjectives() { + const { control, watch } = useFormContext(); const budgetingSelect = useGeneratedHtmlId({ prefix: 'budgetingSelect' }); const timeWindowSelect = useGeneratedHtmlId({ prefix: 'timeWindowSelect' }); @@ -112,7 +108,7 @@ export function SloEditFormObjectives({ control, watch }: Props) { {watch('budgetingMethod') === 'timeslices' ? ( <> - + ) : null} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.stories.tsx index 7bdd33cf741bd..74320a2bf0ef2 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.stories.tsx @@ -10,10 +10,7 @@ import { ComponentStory } from '@storybook/react'; import { FormProvider, useForm } from 'react-hook-form'; import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; -import { - SloEditFormObjectivesTimeslices as Component, - Props, -} from './slo_edit_form_objectives_timeslices'; +import { SloEditFormObjectivesTimeslices as Component } from './slo_edit_form_objectives_timeslices'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../constants'; export default { @@ -22,11 +19,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: Props) => { +const Template: ComponentStory = () => { const methods = useForm({ defaultValues: SLO_EDIT_FORM_DEFAULT_VALUES }); return ( - + ); }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.tsx index 971c2b5fb30ce..2d18c57c203c4 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objectives_timeslices.tsx @@ -8,14 +8,11 @@ import React from 'react'; import { EuiFieldNumber, EuiFlexGrid, EuiFlexItem, EuiFormLabel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Control, Controller } from 'react-hook-form'; +import { Controller, useFormContext } from 'react-hook-form'; import type { CreateSLOInput } from '@kbn/slo-schema'; -export interface Props { - control: Control; -} - -export function SloEditFormObjectivesTimeslices({ control }: Props) { +export function SloEditFormObjectivesTimeslices() { + const { control } = useFormContext(); return ( diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts index 7723bd5ce3f99..165d40cf07c37 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts @@ -22,6 +22,7 @@ import { SLO, APMTransactionDurationIndicator } from '../../../domain/models'; import { getElastichsearchQueryOrThrow, TransformGenerator } from '.'; import { DEFAULT_APM_INDEX } from './constants'; import { Query } from './types'; +import { parseIndex } from './common'; export class ApmTransactionDurationTransformGenerator extends TransformGenerator { public getTransformParams(slo: SLO): TransformPutTransformRequest { @@ -91,7 +92,7 @@ export class ApmTransactionDurationTransformGenerator extends TransformGenerator } return { - index: indicator.params.index ?? DEFAULT_APM_INDEX, + index: parseIndex(indicator.params.index ?? DEFAULT_APM_INDEX), runtime_mappings: this.buildCommonRuntimeMappings(slo), query: { bool: { diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts index 3c26ebfcf146e..6288bcfe3ab4e 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts @@ -23,6 +23,7 @@ import { import { APMTransactionErrorRateIndicator, SLO } from '../../../domain/models'; import { DEFAULT_APM_INDEX } from './constants'; import { Query } from './types'; +import { parseIndex } from './common'; const ALLOWED_STATUS_CODES = ['2xx', '3xx', '4xx', '5xx']; const DEFAULT_GOOD_STATUS_CODES = ['2xx', '3xx', '4xx']; @@ -96,7 +97,7 @@ export class ApmTransactionErrorRateTransformGenerator extends TransformGenerato } return { - index: indicator.params.index ?? DEFAULT_APM_INDEX, + index: parseIndex(indicator.params.index ?? DEFAULT_APM_INDEX), runtime_mappings: this.buildCommonRuntimeMappings(slo), query: { bool: { diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/common.test.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/common.test.ts new file mode 100644 index 0000000000000..ba9856860ec84 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/common.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { parseIndex } from './common'; + +describe('common', () => { + describe('parseIndex', () => { + it.each([ + ['foo-*', 'foo-*'], + ['foo-*,bar-*', ['foo-*', 'bar-*']], + ['remote:foo-*', 'remote:foo-*'], + ['remote:foo*,bar-*', ['remote:foo*', 'remote:bar-*']], + ])("parses the index '%s' correctly", (index, expected) => { + expect(parseIndex(index)).toEqual(expected); + }); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts index b9426ef5f5a77..54197076d359f 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts @@ -15,3 +15,17 @@ export function getElastichsearchQueryOrThrow(kuery: string) { throw new InvalidTransformError(`Invalid KQL: ${kuery}`); } } + +export function parseIndex(index: string): string | string[] { + if (index.indexOf(',') > -1) { + if (index.indexOf(':') > -1) { + const indexParts = index.split(':'); // "remote_name:foo-*,bar*" + const remoteName = indexParts[0]; + return indexParts[1].split(',').map((idx) => `${remoteName}:${idx}`); // [ "remote_name:foo-*", "remote_name:bar-*"] + } + + return index.split(','); + } + + return index; +} diff --git a/x-pack/plugins/profiling/public/components/flame_graphs_view/index.tsx b/x-pack/plugins/profiling/public/components/flame_graphs_view/index.tsx index 078ee3e0e59ac..fab21b235c2ff 100644 --- a/x-pack/plugins/profiling/public/components/flame_graphs_view/index.tsx +++ b/x-pack/plugins/profiling/public/components/flame_graphs_view/index.tsx @@ -15,7 +15,7 @@ import { EuiTitle, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { pick } from 'lodash'; +import { get } from 'lodash'; import React, { useState } from 'react'; import { FlameGraphComparisonMode, FlameGraphNormalizationMode } from '../../../common/flamegraph'; import { useProfilingParams } from '../../hooks/use_profiling_params'; @@ -85,9 +85,31 @@ export function FlameGraphsView({ children }: { children: React.ReactElement }) const comparisonMode = 'comparisonMode' in query ? query.comparisonMode : FlameGraphComparisonMode.Absolute; - const normalizationMode = 'normalizationMode' in query ? query.normalizationMode : undefined; - const baseline = 'baseline' in query ? query.baseline : 1; - const comparison = 'comparison' in query ? query.comparison : 1; + const normalizationMode: FlameGraphNormalizationMode = get( + query, + 'normalizationMode', + FlameGraphNormalizationMode.Time + ); + + const baselineScale: number = get(query, 'baseline', 1); + const comparisonScale: number = get(query, 'comparison', 1); + + const totalSeconds = + (new Date(timeRange.end).getTime() - new Date(timeRange.start).getTime()) / 1000; + const totalComparisonSeconds = + (new Date(comparisonTimeRange.end!).getTime() - + new Date(comparisonTimeRange.start!).getTime()) / + 1000; + + const baselineTime = 1; + const comparisonTime = totalSeconds / totalComparisonSeconds; + + const normalizationOptions: FlameGraphNormalizationOptions = { + baselineScale, + baselineTime, + comparisonScale, + comparisonTime, + }; const { services: { fetchElasticFlamechart }, @@ -247,33 +269,25 @@ export function FlameGraphsView({ children }: { children: React.ReactElement }) { + onChange={(mode, options) => { profilingRouter.push(routePath, { path: routePath, - query: { - ...query, - ...pick(options, 'baseline', 'comparison'), - normalizationMode: options.mode, - }, + query: + mode === FlameGraphNormalizationMode.Scale + ? { + ...query, + baseline: options.baselineScale, + comparison: options.comparisonScale, + normalizationMode: mode, + } + : { + ...query, + normalizationMode: mode, + }, }); }} - totalSeconds={ - (new Date(timeRange.end).getTime() - new Date(timeRange.start).getTime()) / 1000 - } - comparisonTotalSeconds={ - (new Date(comparisonTimeRange.end!).getTime() - - new Date(comparisonTimeRange.start!).getTime()) / - 1000 - } - options={ - (normalizationMode === FlameGraphNormalizationMode.Time - ? { mode: FlameGraphNormalizationMode.Time } - : { - mode: FlameGraphNormalizationMode.Scale, - baseline, - comparison, - }) as FlameGraphNormalizationOptions - } + mode={normalizationMode} + options={normalizationOptions} /> @@ -308,8 +322,16 @@ export function FlameGraphsView({ children }: { children: React.ReactElement }) primaryFlamegraph={data?.primaryFlamegraph} comparisonFlamegraph={data?.comparisonFlamegraph} comparisonMode={comparisonMode} - baseline={baseline} - comparison={comparison} + baseline={ + normalizationMode === FlameGraphNormalizationMode.Time + ? baselineTime + : baselineScale + } + comparison={ + normalizationMode === FlameGraphNormalizationMode.Time + ? comparisonTime + : comparisonScale + } showInformationWindow={showInformationWindow} onInformationWindowClose={() => { setShowInformationWindow(false); diff --git a/x-pack/plugins/profiling/public/components/flame_graphs_view/normalization_menu.tsx b/x-pack/plugins/profiling/public/components/flame_graphs_view/normalization_menu.tsx index 9a6eaba2af677..06007bd09a767 100644 --- a/x-pack/plugins/profiling/public/components/flame_graphs_view/normalization_menu.tsx +++ b/x-pack/plugins/profiling/public/components/flame_graphs_view/normalization_menu.tsx @@ -27,19 +27,17 @@ import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; import { FlameGraphNormalizationMode } from '../../../common/flamegraph'; -export type FlameGraphNormalizationOptions = - | { - mode: FlameGraphNormalizationMode.Scale; - baseline: number; - comparison: number; - } - | { mode: FlameGraphNormalizationMode.Time }; +export interface FlameGraphNormalizationOptions { + baselineScale: number; + baselineTime: number; + comparisonScale: number; + comparisonTime: number; +} interface Props { + mode: FlameGraphNormalizationMode; options: FlameGraphNormalizationOptions; - totalSeconds: number; - comparisonTotalSeconds: number; - onChange: (options: FlameGraphNormalizationOptions) => void; + onChange: (mode: FlameGraphNormalizationMode, options: FlameGraphNormalizationOptions) => void; } const SCALE_LABEL = i18n.translate('xpack.profiling.flameGraphNormalizationMenu.scale', { @@ -57,19 +55,6 @@ const NORMALIZE_BY_LABEL = i18n.translate( } ); -function getScaleFactorsBasedOnTime({ - totalSeconds, - comparisonTotalSeconds, -}: { - totalSeconds: number; - comparisonTotalSeconds: number; -}) { - return { - baseline: 1, - comparison: totalSeconds / comparisonTotalSeconds, - }; -} - export function NormalizationMenu(props: Props) { const [isPopoverOpen, setIsPopoverOpen] = useState(false); @@ -78,26 +63,18 @@ export function NormalizationMenu(props: Props) { const baselineScaleFactorInputId = useGeneratedHtmlId({ prefix: 'baselineScaleFactor' }); const comparisonScaleFactorInputId = useGeneratedHtmlId({ prefix: 'comparisonScaleFactor' }); + const [mode, setMode] = useState(props.mode); const [options, setOptions] = useState(props.options); useEffect(() => { + setMode(props.mode); setOptions(props.options); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - props.options.mode, - // @ts-expect-error can't refine because ESLint will complain - props.options.baseline, - // @ts-expect-error can't refine because ESLint will complain - props.options.comparison, - ]); + }, [props.mode, props.options]); const { baseline, comparison } = - options.mode === FlameGraphNormalizationMode.Time - ? getScaleFactorsBasedOnTime({ - comparisonTotalSeconds: props.comparisonTotalSeconds, - totalSeconds: props.totalSeconds, - }) - : { comparison: options.comparison, baseline: options.baseline }; + mode === FlameGraphNormalizationMode.Time + ? { comparison: options.comparisonTime, baseline: options.baselineTime } + : { comparison: options.comparisonScale, baseline: options.baselineScale }; return ( - {props.options.mode === FlameGraphNormalizationMode.Scale ? SCALE_LABEL : TIME_LABEL} + {props.mode === FlameGraphNormalizationMode.Scale ? SCALE_LABEL : TIME_LABEL} } @@ -183,17 +160,12 @@ export function NormalizationMenu(props: Props) { buttonSize="compressed" isFullWidth onChange={(id, value) => { - setOptions((prevOptions) => ({ - ...prevOptions, - ...(id === FlameGraphNormalizationMode.Time - ? { mode: FlameGraphNormalizationMode.Time } - : { mode: FlameGraphNormalizationMode.Scale, baseline: 1, comparison: 1 }), - })); + setMode(id as FlameGraphNormalizationMode); }} legend={i18n.translate('xpack.profiling.flameGraphNormalizationMode.selectModeLegend', { defaultMessage: 'Select a normalization mode for the flamegraph', })} - idSelected={options.mode} + idSelected={mode} options={[ { id: FlameGraphNormalizationMode.Scale, @@ -223,9 +195,14 @@ export function NormalizationMenu(props: Props) { id={baselineScaleFactorInputId} value={baseline} onChange={(e) => { - setOptions((prevOptions) => ({ ...prevOptions, baseline: e.target.valueAsNumber })); + if (mode === FlameGraphNormalizationMode.Scale) { + setOptions((prevOptions) => ({ + ...prevOptions, + baselineScale: e.target.valueAsNumber, + })); + } }} - disabled={options.mode === FlameGraphNormalizationMode.Time} + disabled={mode === FlameGraphNormalizationMode.Time} /> @@ -246,18 +223,20 @@ export function NormalizationMenu(props: Props) { id={comparisonScaleFactorInputId} value={comparison} onChange={(e) => { - setOptions((prevOptions) => ({ - ...prevOptions, - comparison: e.target.valueAsNumber, - })); + if (mode === FlameGraphNormalizationMode.Scale) { + setOptions((prevOptions) => ({ + ...prevOptions, + comparisonScale: e.target.valueAsNumber, + })); + } }} - disabled={options.mode === FlameGraphNormalizationMode.Time} + disabled={mode === FlameGraphNormalizationMode.Time} /> { - props.onChange(options); + props.onChange(mode, options); setIsPopoverOpen(false); }} fullWidth diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts deleted file mode 100644 index d2b5f88994658..0000000000000 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - ALERT_FLYOUT, - SUMMARY_VIEW_PREVALENCE_CELL, - SUMMARY_VIEW_INVESTIGATE_IN_TIMELINE_BUTTON, - INSIGHTS_RELATED_ALERTS_BY_SESSION, - INSIGHTS_INVESTIGATE_IN_TIMELINE_BUTTON, - INSIGHTS_RELATED_ALERTS_BY_ANCESTRY, - INSIGHTS_INVESTIGATE_ANCESTRY_ALERTS_IN_TIMELINE_BUTTON, -} from '../../screens/alerts_details'; -import { QUERY_TAB_BUTTON, TIMELINE_TITLE } from '../../screens/timeline'; - -import { expandFirstAlert } from '../../tasks/alerts'; -import { verifyInsightCount } from '../../tasks/alerts_details'; -import { setStartDate } from '../../tasks/date_picker'; -import { closeTimeline } from '../../tasks/timeline'; -import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; -import { cleanKibana } from '../../tasks/common'; -import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; -import { login, visitWithoutDateRange } from '../../tasks/login'; - -import { getNewRule } from '../../objects/rule'; - -import { ALERTS_URL } from '../../urls/navigation'; - -describe('Alert Flyout', () => { - before(() => { - cleanKibana(); - login(); - createCustomRuleEnabled(getNewRule(), 'rule1'); - }); - - beforeEach(() => { - visitWithoutDateRange(ALERTS_URL); - const dateContainingAllEvents = 'Jul 27, 2015 @ 00:00:00.000'; - setStartDate(dateContainingAllEvents); - waitForAlertsToPopulate(); - expandFirstAlert(); - }); - - afterEach(() => { - closeTimeline(); - }); - - it('Opens a new timeline investigation (from a prevalence field)', () => { - cy.get(SUMMARY_VIEW_PREVALENCE_CELL) - .first() - .invoke('text') - .then((alertCount) => { - // Click on the first button that lets us investigate in timeline - cy.get(ALERT_FLYOUT).find(SUMMARY_VIEW_INVESTIGATE_IN_TIMELINE_BUTTON).first().click(); - - // Make sure a new timeline is created and opened - cy.get(TIMELINE_TITLE).should('contain.text', 'Untitled timeline'); - - // The alert count in this timeline should match the count shown on the alert flyout - cy.get(QUERY_TAB_BUTTON).should('contain.text', alertCount); - }); - }); - - it('Opens a new timeline investigation (from an insights module)', () => { - verifyInsightCount({ - tableSelector: INSIGHTS_RELATED_ALERTS_BY_SESSION, - investigateSelector: INSIGHTS_INVESTIGATE_IN_TIMELINE_BUTTON, - }); - }); - - it('Opens a new timeline investigation with alert ids from the process ancestry', () => { - verifyInsightCount({ - tableSelector: INSIGHTS_RELATED_ALERTS_BY_ANCESTRY, - investigateSelector: INSIGHTS_INVESTIGATE_ANCESTRY_ALERTS_IN_TIMELINE_BUTTON, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts index e5663f6f4c10b..d8087294d4ed4 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts @@ -8,8 +8,10 @@ import { getNewRule } from '../../objects/rule'; import { CELL_COPY_BUTTON, FILTER_BADGE, SHOW_TOP_N_HEADER } from '../../screens/alerts'; import { + ALERT_TABLE_ACTIONS_HEADER, ALERT_TABLE_FILE_NAME_HEADER, ALERT_TABLE_FILE_NAME_VALUES, + ALERT_TABLE_SEVERITY_HEADER, ALERT_TABLE_SEVERITY_VALUES, PROVIDER_BADGE, } from '../../screens/timeline'; @@ -21,134 +23,157 @@ import { showTopNAlertProperty, clickExpandActions, filterOutAlertProperty, + closeTopNAlertProperty, } from '../../tasks/alerts'; import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; import { cleanKibana } from '../../tasks/common'; import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; import { login, visit } from '../../tasks/login'; -import { fillAddFilterForm, fillKqlQueryBar, openAddFilterPopover } from '../../tasks/search_bar'; -import { openActiveTimeline } from '../../tasks/timeline'; +import { + clearKqlQueryBar, + fillAddFilterForm, + fillKqlQueryBar, + openAddFilterPopover, + removeKqlFilter, +} from '../../tasks/search_bar'; +import { closeTimeline, openActiveTimeline, removeDataProvider } from '../../tasks/timeline'; import { ALERTS_URL } from '../../urls/navigation'; -describe('Alerts cell actions', () => { +describe('Alerts cell actions', { testIsolation: false }, () => { before(() => { cleanKibana(); login(); + createCustomRuleEnabled(getNewRule()); + visit(ALERTS_URL); + waitForAlertsToPopulate(); }); - context('Opening alerts', () => { - before(() => { - createCustomRuleEnabled(getNewRule()); + describe('Filter', () => { + afterEach(() => { + removeKqlFilter(); + scrollAlertTableColumnIntoView(ALERT_TABLE_ACTIONS_HEADER); }); - beforeEach(() => { - visit(ALERTS_URL); - waitForAlertsToPopulate(); + it('should filter for a non-empty property', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_HEADER); + filterForAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(FILTER_BADGE).first().should('have.text', `kibana.alert.severity: ${severityVal}`); + }); }); - describe('Filter', () => { - it('should filter for a non-empty property', () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then((severityVal) => { - scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); - filterForAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); - cy.get(FILTER_BADGE) - .first() - .should('have.text', `kibana.alert.severity: ${severityVal}`); - }); - }); - - it('should filter for an empty property', () => { - // add query condition to make sure the field is empty - fillKqlQueryBar('not file.name: *{enter}'); - scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); - filterForAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); - - cy.get(FILTER_BADGE).first().should('have.text', 'NOT file.name: exists'); - }); - - it('should filter out a non-empty property', () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then((severityVal) => { - scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); - filterOutAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); - cy.get(FILTER_BADGE) - .first() - .should('have.text', `NOT kibana.alert.severity: ${severityVal}`); - }); - }); + it('should filter for an empty property', () => { + // add query condition to make sure the field is empty + fillKqlQueryBar('not file.name: *{enter}'); - it('should filter out an empty property', () => { - // add query condition to make sure the field is empty - fillKqlQueryBar('not file.name: *{enter}'); + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + filterForAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); - scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); - filterOutAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); + cy.get(FILTER_BADGE).first().should('have.text', 'NOT file.name: exists'); - cy.get(FILTER_BADGE).first().should('have.text', 'file.name: exists'); - }); + clearKqlQueryBar(); }); - describe('Add to timeline', () => { - it('should add a non-empty property to default timeline', () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then((severityVal) => { - scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); - addAlertPropertyToTimeline(ALERT_TABLE_SEVERITY_VALUES, 0); - openActiveTimeline(); - cy.get(PROVIDER_BADGE) - .first() - .should('have.text', `kibana.alert.severity: "${severityVal}"`); - }); - }); - - it('should add an empty property to default timeline', () => { - // add condition to make sure the field is empty - openAddFilterPopover(); - fillAddFilterForm({ key: 'file.name', operator: 'does not exist' }); - scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); - addAlertPropertyToTimeline(ALERT_TABLE_FILE_NAME_VALUES, 0); - openActiveTimeline(); - cy.get(PROVIDER_BADGE).first().should('have.text', 'NOT file.name exists'); - }); + it('should filter out a non-empty property', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_HEADER); + filterOutAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(FILTER_BADGE) + .first() + .should('have.text', `NOT kibana.alert.severity: ${severityVal}`); + }); }); - describe('Show Top N', () => { - it('should show top for a property', () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then(() => { - scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); - showTopNAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); - cy.get(SHOW_TOP_N_HEADER).first().should('have.text', `Top kibana.alert.severity`); - }); - }); + it('should filter out an empty property', () => { + // add query condition to make sure the field is empty + fillKqlQueryBar('not file.name: *{enter}'); + + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + filterOutAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); + + cy.get(FILTER_BADGE).first().should('have.text', 'file.name: exists'); + + clearKqlQueryBar(); + }); + }); + + describe('Add to timeline', () => { + afterEach(() => { + removeDataProvider(); + closeTimeline(); + scrollAlertTableColumnIntoView(ALERT_TABLE_ACTIONS_HEADER); + }); + + it('should add a non-empty property to default timeline', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); + addAlertPropertyToTimeline(ALERT_TABLE_SEVERITY_VALUES, 0); + openActiveTimeline(); + cy.get(PROVIDER_BADGE) + .first() + .should('have.text', `kibana.alert.severity: "${severityVal}"`); + }); + }); + + it('should add an empty property to default timeline', () => { + // add condition to make sure the field is empty + openAddFilterPopover(); + + fillAddFilterForm({ key: 'file.name', operator: 'does not exist' }); + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + addAlertPropertyToTimeline(ALERT_TABLE_FILE_NAME_VALUES, 0); + openActiveTimeline(); + cy.get(PROVIDER_BADGE).first().should('have.text', 'NOT file.name exists'); + }); + }); + + describe('Show Top N', () => { + afterEach(() => { + closeTopNAlertProperty(); + scrollAlertTableColumnIntoView(ALERT_TABLE_ACTIONS_HEADER); + }); + + it('should show top for a property', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then(() => { + scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); + showTopNAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(SHOW_TOP_N_HEADER).first().should('have.text', `Top kibana.alert.severity`); + }); + }); + }); + + describe('Copy to clipboard', () => { + afterEach(() => { + scrollAlertTableColumnIntoView(ALERT_TABLE_ACTIONS_HEADER); }); - describe('Copy to clipboard', () => { - it('should copy to clipboard', () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then(() => { - scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); - cy.window().then((win) => { - cy.stub(win, 'prompt').returns('DISABLED WINDOW PROMPT'); - }); - clickExpandActions(ALERT_TABLE_SEVERITY_VALUES, 0); - cy.get(CELL_COPY_BUTTON).should('exist'); - // We are not able to test the "copy to clipboard" action execution - // due to browsers security limitation accessing the clipboard services. - // We assume external `copy` library works + it('should copy to clipboard', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then(() => { + scrollAlertTableColumnIntoView(ALERT_TABLE_SEVERITY_VALUES); + cy.window().then((win) => { + cy.stub(win, 'prompt').returns('DISABLED WINDOW PROMPT'); }); - }); + clickExpandActions(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(CELL_COPY_BUTTON).should('exist'); + // We are not able to test the "copy to clipboard" action execution + // due to browsers security limitation accessing the clipboard services. + // We assume external `copy` library works + }); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts index 9be3268d02795..af17e1bad39f5 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts @@ -26,7 +26,7 @@ import { getUnmappedRule } from '../../objects/rule'; import { ALERTS_URL } from '../../urls/navigation'; import { tablePageSelector } from '../../screens/table_pagination'; -describe('Alert details with unmapped fields', () => { +describe('Alert details with unmapped fields', { testIsolation: false }, () => { before(() => { cleanKibana(); esArchiverLoad('unmapped_fields'); @@ -37,17 +37,11 @@ describe('Alert details with unmapped fields', () => { expandFirstAlert(); }); - beforeEach(() => { - visitWithoutDateRange(ALERTS_URL); - waitForAlertsToPopulate(); - expandFirstAlert(); - }); - after(() => { esArchiverUnload('unmapped_fields'); }); - it('Displays the unmapped field on the JSON view', () => { + it('should display the unmapped field on the JSON view', () => { const expectedUnmappedValue = 'This is the unmapped field'; openJsonView(); @@ -58,7 +52,7 @@ describe('Alert details with unmapped fields', () => { }); }); - it('Displays the unmapped field on the table', () => { + it('should displays the unmapped field on the table', () => { const expectedUnmappedField = { field: 'unmapped', text: 'This is the unmapped field', @@ -76,7 +70,7 @@ describe('Alert details with unmapped fields', () => { }); // This test makes sure that the table does not overflow horizontally - it('Table does not scroll horizontally', () => { + it('table should not scroll horizontally', () => { openTable(); cy.get(ALERT_FLYOUT) diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts index 5f52041e75d17..15052359a54a9 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts @@ -5,36 +5,91 @@ * 2.0. */ +import { closeTimeline } from '../../tasks/timeline'; import { getNewRule } from '../../objects/rule'; -import { PROVIDER_BADGE } from '../../screens/timeline'; +import { PROVIDER_BADGE, QUERY_TAB_BUTTON, TIMELINE_TITLE } from '../../screens/timeline'; -import { investigateFirstAlertInTimeline } from '../../tasks/alerts'; +import { expandFirstAlert, investigateFirstAlertInTimeline } from '../../tasks/alerts'; import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; import { cleanKibana } from '../../tasks/common'; import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; import { login, visit } from '../../tasks/login'; import { ALERTS_URL } from '../../urls/navigation'; +import { + ALERT_FLYOUT, + INSIGHTS_INVESTIGATE_ANCESTRY_ALERTS_IN_TIMELINE_BUTTON, + INSIGHTS_INVESTIGATE_IN_TIMELINE_BUTTON, + INSIGHTS_RELATED_ALERTS_BY_ANCESTRY, + INSIGHTS_RELATED_ALERTS_BY_SESSION, + SUMMARY_VIEW_INVESTIGATE_IN_TIMELINE_BUTTON, + SUMMARY_VIEW_PREVALENCE_CELL, +} from '../../screens/alerts_details'; +import { verifyInsightCount } from '../../tasks/alerts_details'; -describe('Alerts timeline', () => { +describe('Investigate in timeline', { testIsolation: false }, () => { before(() => { cleanKibana(); login(); createCustomRuleEnabled(getNewRule()); - }); - beforeEach(() => { visit(ALERTS_URL); waitForAlertsToPopulate(); }); - it('Investigate alert in default timeline', () => { - investigateFirstAlertInTimeline(); - cy.get(PROVIDER_BADGE) - .first() - .invoke('text') - .then((eventId) => { - investigateFirstAlertInTimeline(); - cy.get(PROVIDER_BADGE).filter(':visible').should('have.text', eventId); + describe('From alerts table', () => { + after(() => { + closeTimeline(); + }); + + it('should open new timeline from alerts table', () => { + investigateFirstAlertInTimeline(); + cy.get(PROVIDER_BADGE) + .first() + .invoke('text') + .then((eventId) => { + investigateFirstAlertInTimeline(); + cy.get(PROVIDER_BADGE).filter(':visible').should('have.text', eventId); + }); + }); + }); + + describe('From alerts details flyout', () => { + before(() => { + expandFirstAlert(); + }); + + afterEach(() => { + closeTimeline(); + }); + + it('should open a new timeline from a prevalence field', () => { + cy.get(SUMMARY_VIEW_PREVALENCE_CELL) + .first() + .invoke('text') + .then((alertCount) => { + // Click on the first button that lets us investigate in timeline + cy.get(ALERT_FLYOUT).find(SUMMARY_VIEW_INVESTIGATE_IN_TIMELINE_BUTTON).first().click(); + + // Make sure a new timeline is created and opened + cy.get(TIMELINE_TITLE).should('contain.text', 'Untitled timeline'); + + // The alert count in this timeline should match the count shown on the alert flyout + cy.get(QUERY_TAB_BUTTON).should('contain.text', alertCount); + }); + }); + + it('should open a new timeline from an insights module', () => { + verifyInsightCount({ + tableSelector: INSIGHTS_RELATED_ALERTS_BY_SESSION, + investigateSelector: INSIGHTS_INVESTIGATE_IN_TIMELINE_BUTTON, + }); + }); + + it('should open a new timeline with alert ids from the process ancestry', () => { + verifyInsightCount({ + tableSelector: INSIGHTS_RELATED_ALERTS_BY_ANCESTRY, + investigateSelector: INSIGHTS_INVESTIGATE_ANCESTRY_ALERTS_IN_TIMELINE_BUTTON, }); + }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alert_details/navigation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/navigation.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/e2e/detection_alert_details/navigation.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_alerts/navigation.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index fe78833ae76de..adc11f627fc44 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -137,6 +137,8 @@ export const EVENT_CONTAINER_TABLE_NOT_LOADING = export const FILTER_BADGE = '[data-test-subj^="filter-badge"]'; +export const FILTER_BADGE_DELETE = '[data-test-subj="deleteFilter"]'; + export const CELL_FILTER_IN_BUTTON = '[data-test-subj="dataGridColumnCellAction-security-default-cellActions-filterIn"]'; export const CELL_FILTER_OUT_BUTTON = @@ -153,6 +155,8 @@ export const ACTIONS_EXPAND_BUTTON = '[data-test-subj="euiDataGridCellExpandButt export const SHOW_TOP_N_HEADER = '[data-test-subj="topN-container"] [data-test-subj="header-section-title"]'; +export const SHOW_TOP_N_CLOSE_BUTTON = '[data-test-subj="close"]'; + export const ALERTS_HISTOGRAM_LEGEND = '[data-test-subj="alerts-histogram-panel"] [data-test-subj="withHoverActionsButton"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/timeline.ts b/x-pack/plugins/security_solution/cypress/screens/timeline.ts index 1fbe6e7fcaf60..0db357f3a7b7d 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timeline.ts @@ -112,6 +112,8 @@ export const PROCESS_KPI = '[data-test-subj="siem-timeline-process-kpi"'; export const PROVIDER_BADGE = '[data-test-subj="providerBadge"]'; +export const PROVIDER_BADGE_DELETE = '.delete-data-provider'; + export const RESET_FIELDS = '[data-test-subj="fields-browser-container"] [data-test-subj="reset-fields"]'; @@ -295,8 +297,12 @@ export const EDIT_TIMELINE_TOOLTIP = '[data-test-subj="save-timeline-btn-tooltip export const ALERT_TABLE_SEVERITY_VALUES = '[data-test-subj="formatted-field-kibana.alert.severity"]'; +export const ALERT_TABLE_ACTIONS_HEADER = '[data-gridcell-column-id="expandColumn"]'; + export const ALERT_TABLE_FILE_NAME_HEADER = '[data-gridcell-column-id="file.name"]'; +export const ALERT_TABLE_SEVERITY_HEADER = '[data-gridcell-column-id="kibana.alert.severity"]'; + export const ALERT_TABLE_FILE_NAME_VALUES = '[data-gridcell-column-id="file.name"][data-test-subj="dataGridRowCell"]'; // empty column for the test data diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index fbea06c251d5b..8de811b6201ad 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { TOP_N_CONTAINER } from '../screens/network/flows'; import { ADD_EXCEPTION_BTN, ALERT_CHECKBOX, @@ -37,6 +38,7 @@ import { ACTIONS_EXPAND_BUTTON, SELECT_HISTOGRAM, CELL_FILTER_OUT_BUTTON, + SHOW_TOP_N_CLOSE_BUTTON, } from '../screens/alerts'; import { LOADING_INDICATOR, REFRESH_BUTTON } from '../screens/security_header'; import { TIMELINE_COLUMN_SPINNER } from '../screens/timeline'; @@ -332,6 +334,11 @@ export const showTopNAlertProperty = (propertySelector: string, rowIndex: number clickExpandActions(propertySelector, rowIndex); cy.get(CELL_SHOW_TOP_FIELD_BUTTON).first().click({ force: true }); }; +export const closeTopNAlertProperty = () => { + cy.get(TOP_N_CONTAINER).then(() => { + cy.get(SHOW_TOP_N_CLOSE_BUTTON).click(); + }); +}; export const waitForAlerts = () => { /* diff --git a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts index fa3dbbc2589e5..2736b931ba0cf 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { FILTER_BADGE, FILTER_BADGE_DELETE } from '../screens/alerts'; import type { SearchBarFilter } from '../objects/filter'; import { @@ -34,6 +35,18 @@ export const fillKqlQueryBar = (query: string) => { cy.get(GLOBAL_KQL_INPUT).type(query); }; +export const clearKqlQueryBar = () => { + cy.get(GLOBAL_KQL_INPUT).should('be.visible'); + cy.get(GLOBAL_KQL_INPUT).clear(); +}; + +export const removeKqlFilter = () => { + cy.get(FILTER_BADGE).then((el) => { + el.click(); + cy.get(FILTER_BADGE_DELETE).click(); + }); +}; + export const fillAddFilterForm = ({ key, value, operator }: SearchBarFilter) => { cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('exist'); cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('be.visible'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts index 78a4fcb0cf7b1..45b7d4a526dee 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts @@ -79,6 +79,8 @@ import { TIMELINE_LUCENELANGUAGE_BUTTON, TIMELINE_KQLLANGUAGE_BUTTON, TIMELINE_QUERY, + PROVIDER_BADGE, + PROVIDER_BADGE_DELETE, } from '../screens/timeline'; import { REFRESH_BUTTON, TIMELINE } from '../screens/timelines'; import { drag, drop } from './common'; @@ -292,6 +294,12 @@ export const closeTimeline = () => { .should('not.be.visible'); }; +export const removeDataProvider = () => { + cy.get(PROVIDER_BADGE) + .click() + .then(() => cy.get(PROVIDER_BADGE_DELETE).click()); +}; + export const createNewTimeline = () => { cy.get(TIMELINE_SETTINGS_ICON) .filter(':visible') diff --git a/x-pack/plugins/security_solution/public/common/components/error_toast_dispatcher/index.tsx b/x-pack/plugins/security_solution/public/common/components/error_toast_dispatcher/index.tsx index 12f51c78fedab..0a441904a1f6b 100644 --- a/x-pack/plugins/security_solution/public/common/components/error_toast_dispatcher/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/error_toast_dispatcher/index.tsx @@ -31,7 +31,7 @@ const ErrorToastDispatcherComponent: React.FC = ({ toastLifeTimeMs = 5 toast: { color: 'danger', id, - iconType: 'alert', + iconType: 'error', title, errors: message, toastLifeTimeMs, diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx index f51b722af2dec..c74218cf09e80 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx @@ -94,14 +94,7 @@ const testProps = { ], }, alertsCount: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'siem', - doc_count: 2, - }, - ], + value: 2, }, }, pagination: { @@ -142,9 +135,7 @@ describe('grouping container', () => { buckets: [], }, alertsCount: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], + value: 0, }, }; const { getByTestId, queryByTestId } = render( diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx index beb1ee796827a..e0ddd959d8b8d 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx @@ -67,12 +67,9 @@ const GroupingContainerComponent = ({ const groupsNumber = data?.groupsNumber?.value ?? 0; const unitCountText = useMemo(() => { - const count = - data?.alertsCount?.buckets && data?.alertsCount?.buckets.length > 0 - ? data?.alertsCount?.buckets[0].doc_count ?? 0 - : 0; + const count = data?.alertsCount?.value ?? 0; return `${count.toLocaleString()} ${unit && unit(count)}`; - }, [data?.alertsCount?.buckets, unit]); + }, [data?.alertsCount?.value, unit]); const unitGroupsCountText = useMemo( () => `${groupsNumber.toLocaleString()} ${GROUPS_UNIT(groupsNumber)}`, diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/query/index.ts b/x-pack/plugins/security_solution/public/common/components/grouping/query/index.ts index 5abd10f1c2575..8a0242e8cc3ae 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/query/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/grouping/query/index.ts @@ -6,12 +6,7 @@ */ import { isEmpty } from 'lodash/fp'; -import type { - GroupingQueryArgs, - GroupingQuery, - SubAggregation, - TermsOrCardinalityAggregation, -} from './types'; +import type { GroupingQueryArgs, GroupingQuery, NamedAggregation } from './types'; /** The maximum number of items to render */ export const DEFAULT_STACK_BY_FIELD0_SIZE = 10; export const DEFAULT_STACK_BY_FIELD1_SIZE = 10; @@ -27,8 +22,8 @@ const getOptionalSubAggregation = ({ stackByMultipleFields1Size: number; stackByMultipleFields1From?: number; stackByMultipleFields1Sort?: Array<{ [category: string]: { order: 'asc' | 'desc' } }>; - additionalStatsAggregationsFields1: TermsOrCardinalityAggregation[]; -}): SubAggregation | {} => + additionalStatsAggregationsFields1: NamedAggregation[]; +}): NamedAggregation | {} => stackByMultipleFields1 != null && !isEmpty(stackByMultipleFields1) ? { stackByMultipleFields1: { diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/query/types.ts b/x-pack/plugins/security_solution/public/common/components/grouping/query/types.ts index 853806a681161..4f1eb464e6fa6 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/query/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/grouping/query/types.ts @@ -17,43 +17,31 @@ interface RangeAgg { range: { '@timestamp': { gte: string; lte: string } }; } -export interface TermsOrCardinalityAggregation { - [category: string]: - | { - cardinality: estypes.AggregationsAggregationContainer['cardinality']; - } - | { - terms: estypes.AggregationsAggregationContainer['terms']; - }; -} +export type NamedAggregation = Record; export interface GroupingQueryArgs { additionalFilters: BoolAgg[]; from: string; runtimeMappings?: MappingRuntimeFields; - additionalAggregationsRoot?: TermsOrCardinalityAggregation[]; + additionalAggregationsRoot?: NamedAggregation[]; stackByMultipleFields0: string[]; stackByMultipleFields0Size?: number; stackByMultipleFields0From?: number; stackByMultipleFields0Sort?: Array<{ [category: string]: { order: 'asc' | 'desc' } }>; - additionalStatsAggregationsFields0: TermsOrCardinalityAggregation[]; + additionalStatsAggregationsFields0: NamedAggregation[]; stackByMultipleFields1: string[] | undefined; stackByMultipleFields1Size?: number; stackByMultipleFields1From?: number; stackByMultipleFields1Sort?: Array<{ [category: string]: { order: estypes.SortOrder } }>; - additionalStatsAggregationsFields1: TermsOrCardinalityAggregation[]; + additionalStatsAggregationsFields1: NamedAggregation[]; to: string; } -export interface SubAggregation extends Record { - bucket_truncate: { bucket_sort: estypes.AggregationsAggregationContainer['bucket_sort'] }; -} - -export interface MainAggregation extends Record { +export interface MainAggregation extends NamedAggregation { stackByMultipleFields0: { terms?: estypes.AggregationsAggregationContainer['terms']; multi_terms?: estypes.AggregationsAggregationContainer['multi_terms']; - aggs: SubAggregation; + aggs: NamedAggregation; }; } diff --git a/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx index 17a2ebe192a44..15178cc72b85a 100644 --- a/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx @@ -299,7 +299,7 @@ describe('Toaster', () => { toast: { color: 'danger', errors: ['message'], - iconType: 'alert', + iconType: 'error', id: '9e1f72a9-7c73-4b7f-a562-09940f7daf4a', title: 'Title', }, diff --git a/x-pack/plugins/security_solution/public/common/components/toasters/utils.test.ts b/x-pack/plugins/security_solution/public/common/components/toasters/utils.test.ts index 34871b2e68efa..8c660a5d0684a 100644 --- a/x-pack/plugins/security_solution/public/common/components/toasters/utils.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/toasters/utils.test.ts @@ -28,7 +28,7 @@ describe('error_to_toaster', () => { toast: { color: 'danger', errors: ['some error 1', 'some error 2'], - iconType: 'alert', + iconType: 'error', id: 'some-made-up-id', title: 'some title', }, @@ -45,7 +45,7 @@ describe('error_to_toaster', () => { toast: { color: 'danger', errors: ['some error 1'], - iconType: 'alert', + iconType: 'error', id: 'some-made-up-id', title: 'some title', }, @@ -64,7 +64,7 @@ describe('error_to_toaster', () => { toast: { color: 'danger', errors: ['something bad happened'], - iconType: 'alert', + iconType: 'error', id: 'some-made-up-id', title: 'some title', }, @@ -82,7 +82,7 @@ describe('error_to_toaster', () => { toast: { color: 'danger', errors: ['Internal Server Error'], - iconType: 'alert', + iconType: 'error', id: 'some-made-up-id', title: 'some title', }, @@ -99,7 +99,7 @@ describe('error_to_toaster', () => { toast: { color: 'danger', errors: ['some error 1'], - iconType: 'alert', + iconType: 'error', id: 'some-made-up-id', title: 'some title', }, @@ -116,7 +116,7 @@ describe('error_to_toaster', () => { toast: { color: 'danger', errors: ['Network Error'], - iconType: 'alert', + iconType: 'error', id: 'some-made-up-id', title: 'some title', }, diff --git a/x-pack/plugins/security_solution/public/common/components/toasters/utils.ts b/x-pack/plugins/security_solution/public/common/components/toasters/utils.ts index 5825f9ad18f06..0114cb2cf4a45 100644 --- a/x-pack/plugins/security_solution/public/common/components/toasters/utils.ts +++ b/x-pack/plugins/security_solution/public/common/components/toasters/utils.ts @@ -30,7 +30,7 @@ export const displayErrorToast = ( id, title: errorTitle, color: 'danger', - iconType: 'alert', + iconType: 'error', errors: errorMessages, }; dispatchToaster({ @@ -87,7 +87,7 @@ export const errorToToaster = ({ title, error, color = 'danger', - iconType = 'alert', + iconType = 'error', dispatchToaster, }: ErrorToToasterArgs) => { let toast: AppToast; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.test.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.test.ts index dc9674967a9fe..33f31d914e5a5 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.test.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.test.ts @@ -45,9 +45,8 @@ describe('getAlertsGroupingQuery', () => { _source: false, aggs: { alertsCount: { - terms: { - exclude: ['alerts'], - field: 'kibana.alert.rule.producer', + value_count: { + field: 'kibana.alert.rule.name', }, }, groupsNumber: { @@ -183,9 +182,8 @@ describe('getAlertsGroupingQuery', () => { _source: false, aggs: { alertsCount: { - terms: { - exclude: ['alerts'], - field: 'kibana.alert.rule.producer', + value_count: { + field: 'process.name', }, }, groupsNumber: { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.ts index 52ae97ca1a512..ed20de72adab2 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/query_builder.ts @@ -7,7 +7,7 @@ import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import type { BoolQuery } from '@kbn/es-query'; -import type { TermsOrCardinalityAggregation } from '../../../../common/components/grouping'; +import type { NamedAggregation } from '../../../../common/components/grouping'; import { getGroupingQuery } from '../../../../common/components/grouping'; const getGroupFields = (groupValue: string) => { @@ -43,12 +43,7 @@ export const getAlertsGroupingQuery = ({ additionalFilters, additionalAggregationsRoot: [ { - alertsCount: { - terms: { - field: 'kibana.alert.rule.producer', - exclude: ['alerts'], - }, - }, + alertsCount: { value_count: { field: selectedGroup } }, }, ...(selectedGroup !== 'none' ? [ @@ -74,8 +69,8 @@ export const getAlertsGroupingQuery = ({ stackByMultipleFields1: [], }); -const getAggregationsByGroupField = (field: string): TermsOrCardinalityAggregation[] => { - const aggMetrics: TermsOrCardinalityAggregation[] = [ +const getAggregationsByGroupField = (field: string): NamedAggregation[] => { + const aggMetrics: NamedAggregation[] = [ { alertsCount: { cardinality: { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index 1b122df170bec..8857f3ca3b079 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -282,8 +282,8 @@ export const AlertsTableComponent: FC = ({ id: tableId, title: i18n.SESSIONS_TITLE, defaultColumns: finalColumns.map((c) => ({ - ...c, initialWidth: DEFAULT_COLUMN_MIN_WIDTH, + ...c, })), }) ); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts index 3eec34c967c21..982e4857086ba 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts @@ -5,15 +5,91 @@ * 2.0. */ +import type { Agent } from '@kbn/fleet-plugin/common'; +import { ENDPOINT_VM_NAME } from '../../tasks/common'; +import { + getAgentByHostName, + getEndpointIntegrationVersion, + reassignAgentPolicy, +} from '../../tasks/fleet'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { getEndpointListPath } from '../../../common/routing'; import { login } from '../../tasks/login'; +import { + AGENT_HOSTNAME_CELL, + TABLE_ROW_ACTIONS, + TABLE_ROW_ACTIONS_MENU, + AGENT_POLICY_CELL, +} from '../../screens/endpoints'; +import { + FLEET_REASSIGN_POLICY_MODAL, + FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON, +} from '../../screens/fleet'; describe('Endpoints page', () => { + const endpointHostname = Cypress.env(ENDPOINT_VM_NAME); + beforeEach(() => { login(); }); - it('Loads the endpoints page', () => { - cy.visit('/app/security/administration/endpoints'); + it('Shows endpoint on the list', () => { + cy.visit(getEndpointListPath({ name: 'endpointList' })); cy.contains('Hosts running Elastic Defend').should('exist'); + cy.getByTestSubj(AGENT_HOSTNAME_CELL).should('have.text', endpointHostname); + }); + + describe('Endpoint reassignment', () => { + let response: IndexedFleetEndpointPolicyResponse; + let initialAgentData: Agent; + + before(() => { + getAgentByHostName(endpointHostname).then((agentData) => { + initialAgentData = agentData; + }); + getEndpointIntegrationVersion().then((version) => { + cy.task('indexFleetEndpointPolicy', { + policyName: `Reassign ${Math.random().toString(36).substr(2, 5)}`, + endpointPackageVersion: version, + }).then((data) => { + response = data; + }); + }); + }); + + beforeEach(() => { + login(); + }); + + after(() => { + if (initialAgentData?.policy_id) { + reassignAgentPolicy(initialAgentData.id, initialAgentData.policy_id); + } + if (response) { + cy.task('deleteIndexedFleetEndpointPolicies', response); + } + }); + + it('User can reassign a single endpoint to a different Agent Configuration', () => { + cy.visit(getEndpointListPath({ name: 'endpointList' })); + const hostname = cy + .getByTestSubj(AGENT_HOSTNAME_CELL) + .filter(`:contains("${endpointHostname}")`); + const tableRow = hostname.parents('tr'); + tableRow.getByTestSubj(TABLE_ROW_ACTIONS).click(); + cy.getByTestSubj(TABLE_ROW_ACTIONS_MENU).contains('Reassign agent policy').click(); + cy.getByTestSubj(FLEET_REASSIGN_POLICY_MODAL) + .find('select') + .select(response.agentPolicies[0].name); + cy.getByTestSubj(FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON).click(); + cy.getByTestSubj(AGENT_HOSTNAME_CELL) + .filter(`:contains("${endpointHostname}")`) + .should('exist'); + cy.getByTestSubj(AGENT_HOSTNAME_CELL) + .filter(`:contains("${endpointHostname}")`) + .parents('tr') + .getByTestSubj(AGENT_POLICY_CELL) + .should('have.text', response.agentPolicies[0].name); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts index 63ca9bc8b5c97..bdf548a833ac6 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts @@ -64,8 +64,8 @@ const visitArtifactTab = (tabId: string) => { const visitPolicyDetailsPage = () => { cy.visit('/app/security/administration/policy'); - cy.getBySel('policyNameCellLink').eq(0).click({ force: true }); - cy.getBySel('policyDetailsPage').should('exist'); + cy.getByTestSubj('policyNameCellLink').eq(0).click({ force: true }); + cy.getByTestSubj('policyDetailsPage').should('exist'); cy.get('#settings').should('exist'); // waiting for Policy Settings tab }; @@ -99,18 +99,18 @@ describe('Artifact tabs in Policy Details page', () => { loginWithPrivilegeRead(testData.privilegePrefix); visitArtifactTab(testData.tabId); - cy.getBySel('policy-artifacts-empty-unexisting').should('exist'); + cy.getByTestSubj('policy-artifacts-empty-unexisting').should('exist'); - cy.getBySel('unexisting-manage-artifacts-button').should('not.exist'); + cy.getByTestSubj('unexisting-manage-artifacts-button').should('not.exist'); }); it(`[ALL] User can add ${testData.title} artifact`, () => { loginWithPrivilegeAll(); visitArtifactTab(testData.tabId); - cy.getBySel('policy-artifacts-empty-unexisting').should('exist'); + cy.getByTestSubj('policy-artifacts-empty-unexisting').should('exist'); - cy.getBySel('unexisting-manage-artifacts-button').should('exist').click(); + cy.getByTestSubj('unexisting-manage-artifacts-button').should('exist').click(); const { formActions, checkResults } = testData.create; @@ -118,18 +118,18 @@ describe('Artifact tabs in Policy Details page', () => { // Add a per policy artifact - but not assign it to any policy cy.get('[data-test-subj$="-perPolicy"]').click(); // test-subjects are generated in different formats, but all ends with -perPolicy - cy.getBySel(`${testData.pagePrefix}-flyout-submitButton`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-flyout-submitButton`).click(); // Check new artifact is in the list for (const checkResult of checkResults) { - cy.getBySel(checkResult.selector).should('have.text', checkResult.value); + cy.getByTestSubj(checkResult.selector).should('have.text', checkResult.value); } - cy.getBySel('policyDetailsPage').should('not.exist'); - cy.getBySel('backToOrigin').contains(/^Back to .+ policy$/); + cy.getByTestSubj('policyDetailsPage').should('not.exist'); + cy.getByTestSubj('backToOrigin').contains(/^Back to .+ policy$/); - cy.getBySel('backToOrigin').click(); - cy.getBySel('policyDetailsPage').should('exist'); + cy.getByTestSubj('backToOrigin').click(); + cy.getByTestSubj('policyDetailsPage').should('exist'); }); }); @@ -144,34 +144,34 @@ describe('Artifact tabs in Policy Details page', () => { loginWithPrivilegeRead(testData.privilegePrefix); visitArtifactTab(testData.tabId); - cy.getBySel('policy-artifacts-empty-unassigned').should('exist'); + cy.getByTestSubj('policy-artifacts-empty-unassigned').should('exist'); - cy.getBySel('unassigned-manage-artifacts-button').should('not.exist'); - cy.getBySel('unassigned-assign-artifacts-button').should('not.exist'); + cy.getByTestSubj('unassigned-manage-artifacts-button').should('not.exist'); + cy.getByTestSubj('unassigned-assign-artifacts-button').should('not.exist'); }); it(`[ALL] User can Manage and Assign ${testData.title} artifacts`, () => { loginWithPrivilegeAll(); visitArtifactTab(testData.tabId); - cy.getBySel('policy-artifacts-empty-unassigned').should('exist'); + cy.getByTestSubj('policy-artifacts-empty-unassigned').should('exist'); // Manage artifacts - cy.getBySel('unassigned-manage-artifacts-button').should('exist').click(); + cy.getByTestSubj('unassigned-manage-artifacts-button').should('exist').click(); cy.location('pathname').should( 'equal', `/app/security/administration/${testData.urlPath}` ); - cy.getBySel('backToOrigin').click(); + cy.getByTestSubj('backToOrigin').click(); // Assign artifacts - cy.getBySel('unassigned-assign-artifacts-button').should('exist').click(); + cy.getByTestSubj('unassigned-assign-artifacts-button').should('exist').click(); - cy.getBySel('artifacts-assign-flyout').should('exist'); - cy.getBySel('artifacts-assign-confirm-button').should('be.disabled'); + cy.getByTestSubj('artifacts-assign-flyout').should('exist'); + cy.getByTestSubj('artifacts-assign-confirm-button').should('be.disabled'); - cy.getBySel(`${testData.artifactName}_checkbox`).click(); - cy.getBySel('artifacts-assign-confirm-button').click(); + cy.getByTestSubj(`${testData.artifactName}_checkbox`).click(); + cy.getByTestSubj('artifacts-assign-confirm-button').click(); }); }); @@ -189,17 +189,17 @@ describe('Artifact tabs in Policy Details page', () => { visitArtifactTab(testData.tabId); // List of artifacts - cy.getBySel('artifacts-collapsed-list-card').should('have.length', 1); - cy.getBySel('artifacts-collapsed-list-card-header-titleHolder').contains( + cy.getByTestSubj('artifacts-collapsed-list-card').should('have.length', 1); + cy.getByTestSubj('artifacts-collapsed-list-card-header-titleHolder').contains( testData.artifactName ); // Cannot assign artifacts - cy.getBySel('artifacts-assign-button').should('not.exist'); + cy.getByTestSubj('artifacts-assign-button').should('not.exist'); // Cannot remove from policy - cy.getBySel('artifacts-collapsed-list-card-header-actions-button').click(); - cy.getBySel('remove-from-policy-action').should('not.exist'); + cy.getByTestSubj('artifacts-collapsed-list-card-header-actions-button').click(); + cy.getByTestSubj('remove-from-policy-action').should('not.exist'); }); it(`[ALL] User can see ${testData.title} artifacts and can assign or remove artifacts from policy`, () => { @@ -207,20 +207,20 @@ describe('Artifact tabs in Policy Details page', () => { visitArtifactTab(testData.tabId); // List of artifacts - cy.getBySel('artifacts-collapsed-list-card').should('have.length', 1); - cy.getBySel('artifacts-collapsed-list-card-header-titleHolder').contains( + cy.getByTestSubj('artifacts-collapsed-list-card').should('have.length', 1); + cy.getByTestSubj('artifacts-collapsed-list-card-header-titleHolder').contains( testData.artifactName ); // Assign artifacts - cy.getBySel('artifacts-assign-button').should('exist').click(); - cy.getBySel('artifacts-assign-flyout').should('exist'); - cy.getBySel('artifacts-assign-cancel-button').click(); + cy.getByTestSubj('artifacts-assign-button').should('exist').click(); + cy.getByTestSubj('artifacts-assign-flyout').should('exist'); + cy.getByTestSubj('artifacts-assign-cancel-button').click(); // Remove from policy - cy.getBySel('artifacts-collapsed-list-card-header-actions-button').click(); - cy.getBySel('remove-from-policy-action').click(); - cy.getBySel('confirmModalConfirmButton').click(); + cy.getByTestSubj('artifacts-collapsed-list-card-header-actions-button').click(); + cy.getByTestSubj('remove-from-policy-action').click(); + cy.getByTestSubj('confirmModalConfirmButton').click(); cy.contains('Successfully removed'); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts index e1536c0515b9e..0e468af132aae 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts @@ -51,10 +51,10 @@ describe('Artifacts pages', () => { describe(`When on the ${testData.title} entries list`, () => { it(`no access - should show no privileges callout`, () => { loginWithoutAccess(`/app/security/administration/${testData.urlPath}`); - cy.getBySel('noPrivilegesPage').should('exist'); - cy.getBySel('empty-page-feature-action').should('exist'); - cy.getBySel(testData.emptyState).should('not.exist'); - cy.getBySel(`${testData.pagePrefix}-emptyState-addButton`).should('not.exist'); + cy.getByTestSubj('noPrivilegesPage').should('exist'); + cy.getByTestSubj('empty-page-feature-action').should('exist'); + cy.getByTestSubj(testData.emptyState).should('not.exist'); + cy.getByTestSubj(`${testData.pagePrefix}-emptyState-addButton`).should('not.exist'); }); it(`read - should show empty state page if there is no ${testData.title} entry and the add button does not exist`, () => { @@ -62,33 +62,33 @@ describe('Artifacts pages', () => { testData.privilegePrefix, `/app/security/administration/${testData.urlPath}` ); - cy.getBySel(testData.emptyState).should('exist'); - cy.getBySel(`${testData.pagePrefix}-emptyState-addButton`).should('not.exist'); + cy.getByTestSubj(testData.emptyState).should('exist'); + cy.getByTestSubj(`${testData.pagePrefix}-emptyState-addButton`).should('not.exist'); }); it(`write - should show empty state page if there is no ${testData.title} entry and the add button exists`, () => { loginWithWriteAccess(`/app/security/administration/${testData.urlPath}`); - cy.getBySel(testData.emptyState).should('exist'); - cy.getBySel(`${testData.pagePrefix}-emptyState-addButton`).should('exist'); + cy.getByTestSubj(testData.emptyState).should('exist'); + cy.getByTestSubj(`${testData.pagePrefix}-emptyState-addButton`).should('exist'); }); it(`write - should create new ${testData.title} entry`, () => { loginWithWriteAccess(`/app/security/administration/${testData.urlPath}`); // Opens add flyout - cy.getBySel(`${testData.pagePrefix}-emptyState-addButton`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-emptyState-addButton`).click(); performUserActions(testData.create.formActions); // Submit create artifact form - cy.getBySel(`${testData.pagePrefix}-flyout-submitButton`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-flyout-submitButton`).click(); // Check new artifact is in the list for (const checkResult of testData.create.checkResults) { - cy.getBySel(checkResult.selector).should('have.text', checkResult.value); + cy.getByTestSubj(checkResult.selector).should('have.text', checkResult.value); } // Title is shown after adding an item - cy.getBySel('header-page-title').contains(testData.title); + cy.getByTestSubj('header-page-title').contains(testData.title); }); it(`read - should not be able to update/delete an existing ${testData.title} entry`, () => { @@ -96,10 +96,10 @@ describe('Artifacts pages', () => { testData.privilegePrefix, `/app/security/administration/${testData.urlPath}` ); - cy.getBySel('header-page-title').contains(testData.title); - cy.getBySel(`${testData.pagePrefix}-card-header-actions-button`).should('not.exist'); - cy.getBySel(`${testData.pagePrefix}-card-cardEditAction`).should('not.exist'); - cy.getBySel(`${testData.pagePrefix}-card-cardDeleteAction`).should('not.exist'); + cy.getByTestSubj('header-page-title').contains(testData.title); + cy.getByTestSubj(`${testData.pagePrefix}-card-header-actions-button`).should('not.exist'); + cy.getByTestSubj(`${testData.pagePrefix}-card-cardEditAction`).should('not.exist'); + cy.getByTestSubj(`${testData.pagePrefix}-card-cardDeleteAction`).should('not.exist'); }); it(`read - should not be able to create a new ${testData.title} entry`, () => { @@ -107,39 +107,39 @@ describe('Artifacts pages', () => { testData.privilegePrefix, `/app/security/administration/${testData.urlPath}` ); - cy.getBySel('header-page-title').contains(testData.title); - cy.getBySel(`${testData.pagePrefix}-pageAddButton`).should('not.exist'); + cy.getByTestSubj('header-page-title').contains(testData.title); + cy.getByTestSubj(`${testData.pagePrefix}-pageAddButton`).should('not.exist'); }); it(`write - should be able to update an existing ${testData.title} entry`, () => { loginWithWriteAccess(`/app/security/administration/${testData.urlPath}`); // Opens edit flyout - cy.getBySel(`${testData.pagePrefix}-card-header-actions-button`).click(); - cy.getBySel(`${testData.pagePrefix}-card-cardEditAction`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-card-header-actions-button`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-card-cardEditAction`).click(); performUserActions(testData.update.formActions); // Submit edit artifact form - cy.getBySel(`${testData.pagePrefix}-flyout-submitButton`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-flyout-submitButton`).click(); for (const checkResult of testData.create.checkResults) { - cy.getBySel(checkResult.selector).should('have.text', checkResult.value); + cy.getByTestSubj(checkResult.selector).should('have.text', checkResult.value); } // Title still shown after editing an item - cy.getBySel('header-page-title').contains(testData.title); + cy.getByTestSubj('header-page-title').contains(testData.title); }); it(`write - should be able to delete the existing ${testData.title} entry`, () => { loginWithWriteAccess(`/app/security/administration/${testData.urlPath}`); // Remove it - cy.getBySel(`${testData.pagePrefix}-card-header-actions-button`).click(); - cy.getBySel(`${testData.pagePrefix}-card-cardDeleteAction`).click(); - cy.getBySel(`${testData.pagePrefix}-deleteModal-submitButton`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-card-header-actions-button`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-card-cardDeleteAction`).click(); + cy.getByTestSubj(`${testData.pagePrefix}-deleteModal-submitButton`).click(); // No card visible after removing it - cy.getBySel(testData.delete.card).should('not.exist'); + cy.getByTestSubj(testData.delete.card).should('not.exist'); // Empty state is displayed after removing last item - cy.getBySel(testData.emptyState).should('exist'); + cy.getByTestSubj(testData.emptyState).should('exist'); }); }); } diff --git a/x-pack/plugins/security_solution/public/management/cypress/screens/endpoints.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/endpoints.ts new file mode 100644 index 0000000000000..199659142adc0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/endpoints.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const AGENT_HOSTNAME_CELL = 'hostnameCellLink'; +export const AGENT_POLICY_CELL = 'policyNameCellLink'; +export const TABLE_ROW_ACTIONS = 'endpointTableRowActions'; +export const TABLE_ROW_ACTIONS_MENU = 'tableRowActionsMenuPanel'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/index.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet.ts similarity index 57% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/index.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/fleet.ts index 8dde6bf2df877..b68cac5c6d495 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/index.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet.ts @@ -5,7 +5,5 @@ * 2.0. */ -export * from './bulk_create_threshold_signals'; -export * from './get_threshold_bucket_filters'; -export * from './get_threshold_signal_history'; -export * from './find_threshold_signals'; +export const FLEET_REASSIGN_POLICY_MODAL = 'agentReassignPolicyModal'; +export const FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON = 'confirmModalConfirmButton'; diff --git a/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.ts b/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.ts new file mode 100644 index 0000000000000..cab36b7c4d175 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// / + +import { createKbnClient } from '../../../../scripts/endpoint/common/stack_services'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + indexFleetEndpointPolicy, + deleteIndexedFleetEndpointPolicies, +} from '../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; + +export const dataLoaders = (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => { + const kbnClient = createKbnClient({ + url: config.env.KIBANA_URL, + username: config.env.ELASTICSEARCH_USERNAME, + password: config.env.ELASTICSEARCH_PASSWORD, + }); + + on('task', { + indexFleetEndpointPolicy: async ({ + policyName, + endpointPackageVersion, + }: { + policyName: string; + endpointPackageVersion: string; + }) => { + return indexFleetEndpointPolicy(kbnClient, policyName, endpointPackageVersion); + }, + deleteIndexedFleetEndpointPolicies: async (indexData: IndexedFleetEndpointPolicyResponse) => { + return deleteIndexedFleetEndpointPolicies(kbnClient, indexData); + }, + }); +}; diff --git a/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts b/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts index 1833e52787e18..a5bcaf43e9b6b 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts @@ -31,13 +31,17 @@ declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Cypress { interface Chainable { - getBySel(...args: Parameters): Chainable>; + getByTestSubj(...args: Parameters): Chainable>; } } } -Cypress.Commands.add('getBySel', (selector, ...args) => - cy.get(`[data-test-subj="${selector}"]`, ...args) -); +Cypress.Commands.addQuery('getByTestSubj', function getByTestSubj(selector, options) { + const getFn = cy.now('get', `[data-test-subj="${selector}"]`, options) as ( + subject: Cypress.Chainable> + ) => Cypress.Chainable>; + + return (subject) => getFn(subject); +}); Cypress.on('uncaught:exception', () => false); diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/artifacts.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/artifacts.ts index 53b191fbe3cfb..8a120b090c33f 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/artifacts.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/artifacts.ts @@ -6,6 +6,10 @@ */ import { PACKAGE_POLICY_API_ROOT } from '@kbn/fleet-plugin/common'; +import type { + ExceptionListItemSchema, + ExceptionListSchema, +} from '@kbn/securitysolution-io-ts-list-types'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { ENDPOINT_ARTIFACT_LISTS, @@ -13,8 +17,7 @@ import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL, } from '@kbn/securitysolution-list-constants'; - -const API_HEADER = { 'kbn-xsrf': 'kibana' }; +import { request } from './common'; export const removeAllArtifacts = () => { for (const listId of ENDPOINT_ARTIFACT_LIST_IDS) { @@ -23,10 +26,9 @@ export const removeAllArtifacts = () => { }; export const removeExceptionsList = (listId: string) => { - cy.request({ + request({ method: 'DELETE', url: `${EXCEPTION_LIST_URL}?list_id=${listId}&namespace_type=agnostic`, - headers: API_HEADER, failOnStatusCode: false, }).then(({ status }) => { expect(status).to.be.oneOf([200, 404]); // should either be success or not found @@ -42,10 +44,9 @@ const ENDPOINT_ARTIFACT_LIST_TYPES = { }; export const createArtifactList = (listId: string) => { - cy.request({ + request({ method: 'POST', url: EXCEPTION_LIST_URL, - headers: API_HEADER, body: { name: listId, description: 'This is a test list', @@ -61,11 +62,9 @@ export const createArtifactList = (listId: string) => { }; export const createPerPolicyArtifact = (name: string, body: object, policyId?: 'all' | string) => { - cy.request({ + request({ method: 'POST', url: EXCEPTION_LIST_ITEM_URL, - - headers: API_HEADER, body: { name, description: '', diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts new file mode 100644 index 0000000000000..8d8f797a99883 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const ENDPOINT_VM_NAME = 'ENDPOINT_VM_NAME'; + +export const API_AUTH = { + user: Cypress.env('ELASTICSEARCH_USERNAME'), + pass: Cypress.env('ELASTICSEARCH_PASSWORD'), +}; + +export const API_HEADERS = { 'kbn-xsrf': 'cypress' }; + +export const request = ( + options: Partial +): Cypress.Chainable> => + cy.request({ + auth: API_AUTH, + headers: API_HEADERS, + ...options, + }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/fleet.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/fleet.ts new file mode 100644 index 0000000000000..14a93368414a0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/fleet.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Agent, GetAgentsResponse, GetInfoResponse } from '@kbn/fleet-plugin/common'; +import { agentRouteService, epmRouteService } from '@kbn/fleet-plugin/common'; +import type { PutAgentReassignResponse } from '@kbn/fleet-plugin/common/types'; +import { request } from './common'; + +export const getEndpointIntegrationVersion = (): Cypress.Chainable => + request({ + url: epmRouteService.getInfoPath('endpoint'), + method: 'GET', + }).then((response) => response.body.item.version); + +export const getAgentByHostName = (hostname: string): Cypress.Chainable => + request({ + url: agentRouteService.getListPath(), + method: 'GET', + qs: { + kuery: `local_metadata.host.hostname: "${hostname}"`, + }, + }).then((response) => response.body.items[0]); + +export const reassignAgentPolicy = ( + agentId: string, + agentPolicyId: string +): Cypress.Chainable> => + request({ + url: agentRouteService.getReassignPath(agentId), + method: 'PUT', + body: { + policy_id: agentPolicyId, + }, + }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/load_endpoint_data.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/load_endpoint_data.ts index 5e6650404e29a..b8029a8528e94 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/load_endpoint_data.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/load_endpoint_data.ts @@ -8,17 +8,17 @@ import { isEmpty } from 'lodash'; import { BASE_ENDPOINT_ROUTE } from '../../../../common/endpoint/constants'; import { runEndpointLoaderScript } from './run_endpoint_loader'; +import { request } from './common'; // Checks for Endpoint data and creates it if needed export const loadEndpointDataForEventFiltersIfNeeded = () => { - cy.request({ + request({ method: 'POST', url: `${BASE_ENDPOINT_ROUTE}/suggestions/eventFilters`, body: { field: 'agent.type', query: '', }, - headers: { 'kbn-xsrf': 'kibana' }, failOnStatusCode: false, }).then(({ body }) => { if (isEmpty(body)) { diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts index a39b102268aae..3ac1cfb1b02e4 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/login.ts @@ -11,6 +11,7 @@ import * as yaml from 'js-yaml'; import type { UrlObject } from 'url'; import Url from 'url'; import type { Role } from '@kbn/security-plugin/common'; +import { request } from './common'; import { getT1Analyst } from '../../../../scripts/endpoint/common/roles_users/t1_analyst'; import { getT2Analyst } from '../../../../scripts/endpoint/common/roles_users/t2_analyst'; import { getHunter } from '../../../../scripts/endpoint/common/roles_users/hunter'; @@ -79,13 +80,6 @@ const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD'; */ const LOGIN_API_ENDPOINT = '/internal/security/login'; -const API_AUTH = { - user: Cypress.env(ELASTICSEARCH_USERNAME), - pass: Cypress.env(ELASTICSEARCH_PASSWORD), -}; - -const API_HEADERS = { 'kbn-xsrf': 'cypress' }; - /** * cy.visit will default to the baseUrl which uses the default kibana test user * This function will override that functionality in cy.visit by building the baseUrl @@ -151,52 +145,40 @@ export const createRoleAndUser = (role: ROLE) => { }; export const createCustomRoleAndUser = (role: string, rolePrivileges: Omit) => { - const env = getCurlScriptEnvVars(); - // post the role - cy.request({ + request({ method: 'PUT', - url: `${env.KIBANA_URL}/api/security/role/${role}`, + url: `/api/security/role/${role}`, body: rolePrivileges, - headers: API_HEADERS, - auth: API_AUTH, }); // post the user associated with the role to elasticsearch - cy.request({ + request({ method: 'POST', - url: `${env.KIBANA_URL}/internal/security/users/${role}`, - headers: API_HEADERS, + url: `/internal/security/users/${role}`, body: { username: role, password: Cypress.env(ELASTICSEARCH_PASSWORD), roles: [role], }, - auth: API_AUTH, }); }; export const deleteRoleAndUser = (role: ROLE) => { - const env = getCurlScriptEnvVars(); - - cy.request({ + request({ method: 'DELETE', - auth: API_AUTH, - headers: API_HEADERS, - url: `${env.KIBANA_URL}/internal/security/users/${role}`, + url: `/internal/security/users/${role}`, }); - cy.request({ + request({ method: 'DELETE', - auth: API_AUTH, - headers: API_HEADERS, - url: `${env.KIBANA_URL}/api/security/role/${role}`, + url: `/api/security/role/${role}`, }); }; export const loginWithUser = (user: User) => { const url = Cypress.config().baseUrl; - cy.request({ + request({ body: { providerType: 'basic', providerName: url && !url.includes('localhost') ? 'cloud-basic' : 'basic', @@ -227,7 +209,7 @@ export const loginWithCustomRole = async (role: string, rolePrivileges: Omit { ); // programmatically authenticate without interacting with the Kibana login page - cy.request({ + request({ body: { providerType: 'basic', providerName: url && !url.includes('localhost') ? 'cloud-basic' : 'basic', @@ -313,7 +295,7 @@ const loginViaConfig = () => { const config = yaml.safeLoad(kibanaDevYml); // programmatically authenticate without interacting with the Kibana login page - cy.request({ + request({ body: { providerType: 'basic', providerName: 'basic', diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/perform_user_actions.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/perform_user_actions.ts index 69c7bd369cdeb..cac6e42720bfd 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/perform_user_actions.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/perform_user_actions.ts @@ -25,7 +25,7 @@ const performAction = (action: FormAction) => { if (action.customSelector) { element = cy.get(action.customSelector); } else { - element = cy.getBySel(action.selector || ''); + element = cy.getByTestSubj(action.selector || ''); } if (action.type === 'click') { diff --git a/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json b/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json index a385fa4c78ec6..7af7e1ce057ef 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json +++ b/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../../../../tsconfig.base.json", "include": [ - "**/*" + "**/*", + "../cypress_endpoint.config.ts" ], "exclude": [ "target/**/*" @@ -26,5 +27,6 @@ "@kbn/securitysolution-list-constants", "@kbn/fleet-plugin", "@kbn/securitysolution-io-ts-list-types", + "@kbn/cypress-config", ] } diff --git a/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts b/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts index d1487b6d990d6..3ee57275cc7fd 100644 --- a/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts +++ b/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts @@ -6,6 +6,8 @@ */ import { defineCypressConfig } from '@kbn/cypress-config'; +// eslint-disable-next-line @kbn/imports/no_boundary_crossing +import { dataLoaders } from './cypress/support/data_loaders'; // eslint-disable-next-line import/no-default-export export default defineCypressConfig({ @@ -37,5 +39,8 @@ export default defineCypressConfig({ supportFile: 'public/management/cypress/support/e2e.ts', specPattern: 'public/management/cypress/e2e/endpoint/*.cy.{js,jsx,ts,tsx}', experimentalRunAllSpecs: true, + setupNodeEvents(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) { + dataLoaders(on, config); + }, }, }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx index 1a05a0f48f050..0a6c82ff452a2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx @@ -12,7 +12,7 @@ import { useUserPrivileges } from '../../../../../common/components/user_privile import { useWithShowEndpointResponder } from '../../../../hooks'; import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import { APP_UI_ID } from '../../../../../../common/constants'; -import { getEndpointDetailsPath } from '../../../../common/routing'; +import { getEndpointDetailsPath, getEndpointListPath } from '../../../../common/routing'; import type { HostMetadata, MaybeImmutable } from '../../../../../../common/endpoint/types'; import { useEndpointSelector } from './hooks'; import { agentPolicies, uiQueryParams } from '../../store/selectors'; @@ -236,6 +236,12 @@ export const useEndpointActionItems = ( agentId: fleetAgentId, })[1] }?openReassignFlyout=true`, + state: { + onDoneNavigateTo: [ + APP_UI_ID, + { path: getEndpointListPath({ name: 'endpointList' }) }, + ], + }, }, href: `${getAppUrl({ appId: 'fleet' })}${ pagePathGetters.agent_details({ diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx index e3ab3b292aaba..ea81ed56eb8e0 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx @@ -291,7 +291,7 @@ export const AlertsByStatus = ({ /> ) : ( { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/utils.ts index 9eef538efe859..717e40e3e6d5f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/utils.ts @@ -7,7 +7,7 @@ import type { Logger } from '@kbn/core/server'; import { APP_PATH } from '../../../../../../common/constants'; -import type { SignalSearchResponse } from '../../../signals/types'; +import type { SignalSearchResponse } from '../../../rule_types/types'; export const getNotificationResultsLink = ({ kibanaSiemAppUrl = APP_PATH, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts index c12dbf9c36d9c..3818ca1403e63 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/create_rule_execution_summary.ts @@ -13,41 +13,56 @@ import { ruleExecutionStatusToNumber, RuleExecutionStatus, } from '../../../../../../common/detection_engine/rule_monitoring'; + import type { RuleParams } from '../../../rule_schema'; export const createRuleExecutionSummary = ( rule: SanitizedRule | ResolvedSanitizedRule ): RuleExecutionSummary | null => { + if (!rule.monitoring) { + // In the rule type the monitoring object is optional because in some cases rules client returns a rule without it. + // For instance, when we call RulesClient.create(). Despite the fact that it's always in the rule saved object, + // even when it was just created: + // https://github.com/elastic/kibana/blob/26eddec70844ffb65e5d3521a7adb52e643c4534/x-pack/plugins/alerting/server/rules_client/methods/create.ts#L155 + return null; + } + + // Data that we need to create rule execution summary is stored in two different "last run" objects within a rule. + + // This last run object is internal to Kibana server and is not exposed via any public HTTP API. + // Alerting Framework keeps it for itself and provides via the RulesClient for solutions. + const lastRunInternal = rule.monitoring.run.last_run; + // This last run object is public - it is exposed via the public Alerting HTTP API. + const lastRunPublic = rule.lastRun; + if (rule.running) { return { last_execution: { - date: new Date().toISOString(), - message: '', - metrics: {}, + date: lastRunInternal.timestamp, status: RuleExecutionStatus.running, status_order: ruleExecutionStatusToNumber(RuleExecutionStatus.running), + message: '', + metrics: {}, }, }; } - if (!rule.lastRun) { + if (!lastRunPublic) { return null; } - const ruleExecutionStatus = ruleLastRunOutcomeToExecutionStatus(rule.lastRun.outcome); + const ruleExecutionStatus = ruleLastRunOutcomeToExecutionStatus(lastRunPublic.outcome); return { last_execution: { - date: rule.monitoring?.run.last_run?.timestamp ?? new Date().toISOString(), + date: lastRunInternal.timestamp, status: ruleExecutionStatus, status_order: ruleExecutionStatusToNumber(ruleExecutionStatus), - message: rule.lastRun?.outcomeMsg?.join(' \n') ?? '', + message: lastRunPublic.outcomeMsg?.join(' \n') ?? '', metrics: { - total_indexing_duration_ms: - rule.monitoring?.run.last_run.metrics.total_indexing_duration_ms ?? undefined, - total_search_duration_ms: - rule.monitoring?.run.last_run.metrics.total_search_duration_ms ?? undefined, - execution_gap_duration_s: rule.monitoring?.run.last_run.metrics.gap_duration_s ?? undefined, + total_indexing_duration_ms: lastRunInternal.metrics.total_indexing_duration_ms ?? undefined, + total_search_duration_ms: lastRunInternal.metrics.total_search_duration_ms ?? undefined, + execution_gap_duration_s: lastRunInternal.metrics.gap_duration_s ?? undefined, }, }, }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/preview/alert_instance_factory_stub.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/alert_instance_factory_stub.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/preview/alert_instance_factory_stub.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/alert_instance_factory_stub.ts index 1b947b1be08a2..f350d2a3cb35f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/preview/alert_instance_factory_stub.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/alert_instance_factory_stub.ts @@ -11,7 +11,7 @@ import type { RuleTypeState, } from '@kbn/alerting-plugin/common'; import { Alert } from '@kbn/alerting-plugin/server/alert'; -import type { RuleParams } from '../../rule_schema'; +import type { RuleParams } from '../../../rule_schema'; export const alertInstanceFactoryStub = < TParams extends RuleParams, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/preview/preview_rule_execution_logger.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/preview_rule_execution_logger.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/preview/preview_rule_execution_logger.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/preview_rule_execution_logger.ts index 978a43a29a878..46cb0e8adfbf4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/preview/preview_rule_execution_logger.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/preview_rule_execution_logger.ts @@ -9,7 +9,7 @@ import type { IRuleExecutionLogService, RuleExecutionContext, StatusChangeArgs, -} from '../../rule_monitoring'; +} from '../../../rule_monitoring'; export interface IPreviewRuleExecutionLogger { factory: IRuleExecutionLogService['createClientForExecutors']; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts index d2133bb0b11b3..7ff1366b8d945 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts @@ -32,8 +32,8 @@ import type { StartPlugins, SetupPlugins } from '../../../../../plugin'; import { buildSiemResponse } from '../../../routes/utils'; import { convertCreateAPIToInternalSchema } from '../../../rule_management'; import type { RuleParams } from '../../../rule_schema'; -import { createPreviewRuleExecutionLogger } from '../../../signals/preview/preview_rule_execution_logger'; -import { parseInterval } from '../../../signals/utils'; +import { createPreviewRuleExecutionLogger } from './preview_rule_execution_logger'; +import { parseInterval } from '../../../rule_types/utils/utils'; import { buildMlAuthz } from '../../../../machine_learning/authz'; import { throwAuthzError } from '../../../../machine_learning/validation'; import { buildRouteValidation } from '../../../../../utils/build_validation/route_validation'; @@ -43,7 +43,7 @@ import type { SecuritySolutionPluginRouter } from '../../../../../types'; import type { RuleExecutionContext, StatusChangeArgs } from '../../../rule_monitoring'; import type { ConfigType } from '../../../../../config'; -import { alertInstanceFactoryStub } from '../../../signals/preview/alert_instance_factory_stub'; +import { alertInstanceFactoryStub } from './alert_instance_factory_stub'; import type { CreateRuleOptions, CreateSecurityRuleTypeWrapperProps, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts index 86966e8193158..7c12639d7efdf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts @@ -7,7 +7,7 @@ import { getThreatMock } from '../../../../../common/detection_engine/schemas/types/threat.mock'; import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; -import { getThreatMappingMock } from '../../signals/threat_mapping/build_threat_mapping_filter.mock'; +import { getThreatMappingMock } from '../../rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.mock'; import type { BaseRuleParams, CompleteRule, @@ -21,7 +21,7 @@ import type { ThresholdRuleParams, } from '..'; import type { SanitizedRuleConfig } from '@kbn/alerting-plugin/common'; -import { sampleRuleGuid } from '../../signals/__mocks__/es_results'; +import { sampleRuleGuid } from '../../rule_types/__mocks__/es_results'; const getBaseRuleParams = (): BaseRuleParams => { return { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/empty_signal_source_hit.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/empty_signal_source_hit.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/empty_signal_source_hit.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/empty_signal_source_hit.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/es_results.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/es_results.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts index a76e3d3d3af7e..228cb67122a26 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts @@ -17,7 +17,7 @@ import { ruleRegistryMocks } from '@kbn/rule-registry-plugin/server/mocks'; import { eventLogServiceMock } from '@kbn/event-log-plugin/server/mocks'; import type { PluginSetupContract as AlertingPluginSetupContract } from '@kbn/alerting-plugin/server'; import type { ConfigType } from '../../../../config'; -import type { AlertAttributes } from '../../signals/types'; +import type { AlertAttributes } from '../types'; import { createRuleMock } from './rule'; import { listMock } from '@kbn/lists-plugin/server/mocks'; import type { QueryRuleParams, RuleParams } from '../../rule_schema'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts index ab6d64e69b58d..15f82e84155cb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts @@ -35,6 +35,8 @@ import { ALERT_ORIGINAL_EVENT, ALERT_THRESHOLD_RESULT, } from '../../../../../common/field_maps/field_names'; +import type { ThresholdSignalHistory } from '../threshold/types'; +import { getThresholdTermsHash } from '../threshold/utils'; export const sampleThresholdAlert = { _id: 'b3ad77a4-65bd-4c4e-89cf-13c46f54bc4d', @@ -126,3 +128,22 @@ export const sampleThresholdAlert = { 'kibana.alert.depth': 1, }, }; + +export const sampleThresholdSignalHistory = (): ThresholdSignalHistory => { + const terms = [ + { + field: 'source.ip', + value: '127.0.0.1', + }, + { + field: 'host.name', + value: 'garden-gnomes', + }, + ]; + return { + [`${getThresholdTermsHash(terms)}`]: { + terms, + lastSignalTimestamp: new Date('2020-12-17T16:28:00Z').getTime(), + }, + }; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts index 5be1d2f23df2d..38ce087fb6aae 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts @@ -21,7 +21,7 @@ import { hasReadIndexPrivileges, hasTimestampFields, isMachineLearningParams, -} from '../signals/utils'; +} from './utils/utils'; import { DEFAULT_MAX_SIGNALS, DEFAULT_SEARCH_AFTER_PAGE_SIZE } from '../../../../common/constants'; import type { CreateSecurityRuleTypeWrapper } from './types'; import { getListClient } from './utils/get_list_client'; @@ -38,9 +38,9 @@ import { bulkCreateFactory, wrapHitsFactory, wrapSequencesFactory } from './fact import { RuleExecutionStatus } from '../../../../common/detection_engine/rule_monitoring'; import { truncateList } from '../rule_monitoring'; import aadFieldConversion from '../routes/index/signal_aad_mapping.json'; -import { extractReferences, injectReferences } from '../signals/saved_object_references'; +import { extractReferences, injectReferences } from './saved_object_references'; import { withSecuritySpan } from '../../../utils/with_security_span'; -import { getInputIndex, DataViewError } from '../signals/get_input_output_index'; +import { getInputIndex, DataViewError } from './utils/get_input_output_index'; import { TIMESTAMP_RUNTIME_FIELD } from './constants'; import { buildTimestampRuntimeMapping } from './utils/build_timestamp_runtime_mapping'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_alert_group_from_sequence.test.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_alert_group_from_sequence.test.ts index 150c98cbee59f..98c5637b59d7a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_alert_group_from_sequence.test.ts @@ -7,22 +7,22 @@ import { ALERT_RULE_CONSUMER } from '@kbn/rule-data-utils'; -import { sampleDocNoSortId, sampleRuleGuid } from '../../../signals/__mocks__/es_results'; +import { sampleDocNoSortId, sampleRuleGuid } from '../__mocks__/es_results'; import { buildAlertGroupFromSequence, objectArrayIntersection, objectPairIntersection, } from './build_alert_group_from_sequence'; -import { SERVER_APP_ID } from '../../../../../../common/constants'; -import { getCompleteRuleMock, getQueryRuleParams } from '../../../rule_schema/mocks'; -import type { QueryRuleParams } from '../../../rule_schema'; -import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; +import { SERVER_APP_ID } from '../../../../../common/constants'; +import { getCompleteRuleMock, getQueryRuleParams } from '../../rule_schema/mocks'; +import type { QueryRuleParams } from '../../rule_schema'; +import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; import { ALERT_ANCESTORS, ALERT_DEPTH, ALERT_BUILDING_BLOCK_TYPE, ALERT_GROUP_ID, -} from '../../../../../../common/field_maps/field_names'; +} from '../../../../../common/field_maps/field_names'; const SPACE_ID = 'space'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_alert_group_from_sequence.ts similarity index 89% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_alert_group_from_sequence.ts index 369f017426315..f03d185c19996 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_alert_group_from_sequence.ts @@ -7,26 +7,26 @@ import { ALERT_UUID } from '@kbn/rule-data-utils'; -import type { ConfigType } from '../../../../../config'; -import type { Ancestor, SignalSource, SignalSourceHit } from '../../../signals/types'; -import { buildAlert, buildAncestors, generateAlertId } from './build_alert'; -import { buildBulkBody } from './build_bulk_body'; -import type { EqlSequence } from '../../../../../../common/detection_engine/types'; -import { generateBuildingBlockIds } from './generate_building_block_ids'; -import type { BuildReasonMessage } from '../../../signals/reason_formatters'; -import type { CompleteRule, RuleParams } from '../../../rule_schema'; -import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; +import type { ConfigType } from '../../../../config'; +import type { Ancestor, SignalSource, SignalSourceHit } from '../types'; +import { buildAlert, buildAncestors, generateAlertId } from '../factories/utils/build_alert'; +import { buildBulkBody } from '../factories/utils/build_bulk_body'; +import type { EqlSequence } from '../../../../../common/detection_engine/types'; +import { generateBuildingBlockIds } from '../factories/utils/generate_building_block_ids'; +import type { BuildReasonMessage } from '../utils/reason_formatters'; +import type { CompleteRule, RuleParams } from '../../rule_schema'; +import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; import { ALERT_BUILDING_BLOCK_TYPE, ALERT_GROUP_ID, ALERT_GROUP_INDEX, -} from '../../../../../../common/field_maps/field_names'; +} from '../../../../../common/field_maps/field_names'; import type { BaseFieldsLatest, EqlBuildingBlockFieldsLatest, EqlShellFieldsLatest, WrappedFieldsLatest, -} from '../../../../../../common/detection_engine/schemas/alerts'; +} from '../../../../../common/detection_engine/schemas/alerts'; /** * Takes N raw documents from ES that form a sequence and builds them into N+1 signals ready to be indexed - diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_eql_search_request.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_eql_search_request.test.ts new file mode 100644 index 0000000000000..571684f1fdcee --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_eql_search_request.test.ts @@ -0,0 +1,432 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; +import { getListClientMock } from '@kbn/lists-plugin/server/services/lists/list_client.mock'; +import { buildExceptionFilter } from '@kbn/lists-plugin/server/services/exception_lists'; +import { buildEqlSearchRequest } from './build_eql_search_request'; + +const emptyFilter = { + bool: { + must: [], + filter: [], + should: [], + must_not: [], + }, +}; + +describe('buildEqlSearchRequest', () => { + test('should build a basic request with time range', () => { + const request = buildEqlSearchRequest({ + query: 'process where true', + index: ['testindex1', 'testindex2'], + from: 'now-5m', + to: 'now', + size: 100, + filters: undefined, + primaryTimestamp: '@timestamp', + secondaryTimestamp: undefined, + runtimeMappings: undefined, + eventCategoryOverride: undefined, + exceptionFilter: undefined, + }); + expect(request).toEqual({ + allow_no_indices: true, + index: ['testindex1', 'testindex2'], + body: { + size: 100, + query: 'process where true', + runtime_mappings: undefined, + filter: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: 'now-5m', + lte: 'now', + format: 'strict_date_optional_time', + }, + }, + }, + emptyFilter, + ], + }, + }, + fields: [ + { + field: '*', + include_unmapped: true, + }, + { + field: '@timestamp', + format: 'strict_date_optional_time', + }, + ], + }, + }); + }); + + test('should build a request with timestamp and event category overrides', () => { + const request = buildEqlSearchRequest({ + query: 'process where true', + index: ['testindex1', 'testindex2'], + from: 'now-5m', + to: 'now', + size: 100, + filters: undefined, + primaryTimestamp: 'event.ingested', + secondaryTimestamp: '@timestamp', + runtimeMappings: undefined, + eventCategoryOverride: 'event.other_category', + timestampField: undefined, + exceptionFilter: undefined, + }); + expect(request).toEqual({ + allow_no_indices: true, + index: ['testindex1', 'testindex2'], + body: { + event_category_field: 'event.other_category', + size: 100, + query: 'process where true', + runtime_mappings: undefined, + filter: { + bool: { + filter: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + range: { + 'event.ingested': { + lte: 'now', + gte: 'now-5m', + format: 'strict_date_optional_time', + }, + }, + }, + { + bool: { + filter: [ + { + range: { + '@timestamp': { + lte: 'now', + gte: 'now-5m', + format: 'strict_date_optional_time', + }, + }, + }, + { + bool: { + must_not: { + exists: { + field: 'event.ingested', + }, + }, + }, + }, + ], + }, + }, + ], + }, + }, + emptyFilter, + ], + }, + }, + fields: [ + { + field: '*', + include_unmapped: true, + }, + { + field: 'event.ingested', + format: 'strict_date_optional_time', + }, + { + field: '@timestamp', + format: 'strict_date_optional_time', + }, + ], + }, + }); + }); + + test('should build a request without @timestamp fallback if secondaryTimestamp is not specified', () => { + const request = buildEqlSearchRequest({ + query: 'process where true', + index: ['testindex1', 'testindex2'], + from: 'now-5m', + to: 'now', + size: 100, + filters: undefined, + primaryTimestamp: 'event.ingested', + secondaryTimestamp: undefined, + runtimeMappings: undefined, + eventCategoryOverride: 'event.other_category', + timestampField: undefined, + exceptionFilter: undefined, + }); + expect(request).toEqual({ + allow_no_indices: true, + index: ['testindex1', 'testindex2'], + body: { + event_category_field: 'event.other_category', + size: 100, + query: 'process where true', + runtime_mappings: undefined, + filter: { + bool: { + filter: [ + { + range: { + 'event.ingested': { + lte: 'now', + gte: 'now-5m', + format: 'strict_date_optional_time', + }, + }, + }, + emptyFilter, + ], + }, + }, + fields: [ + { + field: '*', + include_unmapped: true, + }, + { + field: 'event.ingested', + format: 'strict_date_optional_time', + }, + ], + }, + }); + }); + + test('should build a request with exceptions', async () => { + const { filter } = await buildExceptionFilter({ + listClient: getListClientMock(), + lists: [getExceptionListItemSchemaMock()], + alias: null, + chunkSize: 1024, + excludeExceptions: true, + startedAt: new Date(), + }); + const request = buildEqlSearchRequest({ + query: 'process where true', + index: ['testindex1', 'testindex2'], + from: 'now-5m', + to: 'now', + size: 100, + filters: undefined, + primaryTimestamp: '@timestamp', + secondaryTimestamp: undefined, + runtimeMappings: undefined, + eventCategoryOverride: undefined, + exceptionFilter: filter, + }); + expect(request).toMatchInlineSnapshot(` + Object { + "allow_no_indices": true, + "body": Object { + "event_category_field": undefined, + "fields": Array [ + Object { + "field": "*", + "include_unmapped": true, + }, + Object { + "field": "@timestamp", + "format": "strict_date_optional_time", + }, + ], + "filter": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "format": "strict_date_optional_time", + "gte": "now-5m", + "lte": "now", + }, + }, + }, + Object { + "bool": Object { + "filter": Array [], + "must": Array [], + "must_not": Array [ + Object { + "bool": Object { + "should": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "nested": Object { + "path": "some.parentField", + "query": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "some.parentField.nested.field": "some value", + }, + }, + ], + }, + }, + "score_mode": "none", + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "some.not.nested.field": "some value", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + "should": Array [], + }, + }, + ], + }, + }, + "query": "process where true", + "runtime_mappings": undefined, + "size": 100, + "tiebreaker_field": undefined, + "timestamp_field": undefined, + }, + "index": Array [ + "testindex1", + "testindex2", + ], + } + `); + }); + + test('should build a request with filters', () => { + const filters = [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'exists', + key: 'process.name', + value: 'exists', + }, + query: { + exists: { + field: 'process.name', + }, + }, + }, + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'host.name', + params: { + query: 'Host-b4d9hu1a56', + }, + }, + query: { + match_phrase: { + 'host.name': 'Host-b4d9hu1a56', + }, + }, + }, + ]; + const request = buildEqlSearchRequest({ + query: 'process where true', + index: ['testindex1', 'testindex2'], + from: 'now-5m', + to: 'now', + size: 100, + filters, + primaryTimestamp: '@timestamp', + secondaryTimestamp: undefined, + runtimeMappings: undefined, + exceptionFilter: undefined, + }); + expect(request).toEqual({ + allow_no_indices: true, + index: ['testindex1', 'testindex2'], + body: { + size: 100, + query: 'process where true', + filter: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: 'now-5m', + lte: 'now', + format: 'strict_date_optional_time', + }, + }, + }, + { + bool: { + must: [], + filter: [ + { + exists: { + field: 'process.name', + }, + }, + { + match_phrase: { + 'host.name': 'Host-b4d9hu1a56', + }, + }, + ], + should: [], + must_not: [], + }, + }, + ], + }, + }, + fields: [ + { + field: '*', + include_unmapped: true, + }, + { + field: '@timestamp', + format: 'strict_date_optional_time', + }, + ], + }, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_eql_search_request.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_eql_search_request.ts new file mode 100644 index 0000000000000..3d8910a8e9bab --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/build_eql_search_request.ts @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { Filter } from '@kbn/es-query'; +import type { + RuleFilterArray, + TimestampOverride, +} from '../../../../../common/detection_engine/rule_schema'; +import { buildTimeRangeFilter } from '../utils/build_events_query'; +import { getQueryFilter } from '../utils/get_query_filter'; + +interface BuildEqlSearchRequestParams { + query: string; + index: string[]; + from: string; + to: string; + size: number; + filters: RuleFilterArray | undefined; + primaryTimestamp: TimestampOverride; + secondaryTimestamp: TimestampOverride | undefined; + runtimeMappings: estypes.MappingRuntimeFields | undefined; + eventCategoryOverride?: string; + timestampField?: string; + tiebreakerField?: string; + exceptionFilter: Filter | undefined; +} + +export const buildEqlSearchRequest = ({ + query, + index, + from, + to, + size, + filters, + primaryTimestamp, + secondaryTimestamp, + runtimeMappings, + eventCategoryOverride, + timestampField, + tiebreakerField, + exceptionFilter, +}: BuildEqlSearchRequestParams): estypes.EqlSearchRequest => { + const timestamps = secondaryTimestamp + ? [primaryTimestamp, secondaryTimestamp] + : [primaryTimestamp]; + const docFields = timestamps.map((tstamp) => ({ + field: tstamp, + format: 'strict_date_optional_time', + })); + + const esFilter = getQueryFilter({ + query: '', + language: 'eql', + filters: filters || [], + index, + exceptionFilter, + }); + + const rangeFilter = buildTimeRangeFilter({ + to, + from, + primaryTimestamp, + secondaryTimestamp, + }); + const requestFilter: estypes.QueryDslQueryContainer[] = [rangeFilter, esFilter]; + const fields = [ + { + field: '*', + include_unmapped: true, + }, + ...docFields, + ]; + return { + index, + allow_no_indices: true, + body: { + size, + query, + filter: { + bool: { + filter: requestFilter, + }, + }, + runtime_mappings: runtimeMappings, + timestamp_field: timestampField, + event_category_field: eventCategoryOverride, + tiebreaker_field: tiebreakerField, + fields, + }, + }; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts index 6e31a9753d381..3a22dbf061ebd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/create_eql_alert_type.ts @@ -11,7 +11,7 @@ import { EQL_RULE_TYPE_ID } from '@kbn/securitysolution-rules'; import { SERVER_APP_ID } from '../../../../../common/constants'; import type { EqlRuleParams } from '../../rule_schema'; import { eqlRuleParams } from '../../rule_schema'; -import { eqlExecutor } from '../../signals/executors/eql'; +import { eqlExecutor } from './eql'; import type { CreateRuleOptions, SecurityAlertType } from '../types'; import { validateIndexPatterns } from '../utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/eql.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/eql.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/eql.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/eql.ts index a67a404478b18..492e555422e09 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/eql.ts @@ -14,8 +14,8 @@ import type { } from '@kbn/alerting-plugin/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { Filter } from '@kbn/es-query'; -import { buildEqlSearchRequest } from '../build_events_query'; -import { createEnrichEventsFunction } from '../enrichments'; +import { buildEqlSearchRequest } from './build_eql_search_request'; +import { createEnrichEventsFunction } from '../utils/enrichments'; import type { BulkCreate, @@ -30,8 +30,8 @@ import { createSearchAfterReturnType, makeFloatString, getUnprocessedExceptionsWarnings, -} from '../utils'; -import { buildReasonMessageForEqlAlert } from '../reason_formatters'; +} from '../utils/utils'; +import { buildReasonMessageForEqlAlert } from '../utils/reason_formatters'; import type { CompleteRule, EqlRuleParams } from '../../rule_schema'; import { withSecuritySpan } from '../../../../utils/with_security_span'; import type { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_sequences_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/wrap_sequences_factory.ts similarity index 91% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_sequences_factory.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/wrap_sequences_factory.ts index f20954cf9efbd..650cfb21a71c9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_sequences_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/eql/wrap_sequences_factory.ts @@ -5,8 +5,8 @@ * 2.0. */ -import type { WrapSequences } from '../../signals/types'; -import { buildAlertGroupFromSequence } from './utils/build_alert_group_from_sequence'; +import type { WrapSequences } from '../types'; +import { buildAlertGroupFromSequence } from './build_alert_group_from_sequence'; import type { ConfigType } from '../../../../config'; import type { CompleteRule, RuleParams } from '../../rule_schema'; import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts index 95bc32571f6ea..4e16c8378c03c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts @@ -11,7 +11,7 @@ import { isEmpty } from 'lodash'; import type { PersistenceAlertService } from '@kbn/rule-registry-plugin/server'; import type { AlertWithCommonFieldsLatest } from '@kbn/rule-registry-plugin/common/schemas'; import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; -import { makeFloatString } from '../../signals/utils'; +import { makeFloatString } from '../utils/utils'; import type { RefreshTypes } from '../../types'; import type { BaseFieldsLatest, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/index.ts index 4d93238974487..fb2d973f11ddc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/index.ts @@ -7,4 +7,4 @@ export * from './bulk_create_factory'; export * from './wrap_hits_factory'; -export * from './wrap_sequences_factory'; +export * from '../eql/wrap_sequences_factory'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts index 685d85d40a6b4..2b6702f591ab4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts @@ -27,9 +27,9 @@ import { } from '@kbn/rule-data-utils'; import { flattenWithPrefix } from '@kbn/securitysolution-rules'; -import { sampleDocNoSortIdWithTimestamp } from '../../../signals/__mocks__/es_results'; +import { sampleDocNoSortIdWithTimestamp } from '../../__mocks__/es_results'; import { buildAlert, buildParent, buildAncestors, additionalAlertFields } from './build_alert'; -import type { Ancestor, SignalSourceHit } from '../../../signals/types'; +import type { Ancestor, SignalSourceHit } from '../../types'; import { getListArrayMock } from '../../../../../../common/detection_engine/schemas/types/lists.mock'; import { SERVER_APP_ID } from '../../../../../../common/constants'; import { EVENT_DATASET } from '../../../../../../common/cti/constants'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts index cbc1d2cc89f96..d206fa06704f0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts @@ -43,13 +43,14 @@ import { flattenWithPrefix } from '@kbn/securitysolution-rules'; import { createHash } from 'crypto'; -import type { BaseSignalHit, SimpleHit, ThresholdResult } from '../../../signals/types'; +import type { BaseSignalHit, SimpleHit } from '../../types'; +import type { ThresholdResult } from '../../threshold/types'; import { getField, getValidDateFromDoc, isWrappedDetectionAlert, isWrappedSignalHit, -} from '../../../signals/utils'; +} from '../../utils/utils'; import { SERVER_APP_ID } from '../../../../../../common/constants'; import type { SearchTypes } from '../../../../telemetry/types'; import { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_bulk_body.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_bulk_body.ts index 5a44a4d06260a..cd7351362db0b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_bulk_body.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_bulk_body.ts @@ -10,16 +10,16 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { BaseHit, SearchTypes } from '../../../../../../common/detection_engine/types'; import type { ConfigType } from '../../../../../config'; -import type { BuildReasonMessage } from '../../../signals/reason_formatters'; -import { getMergeStrategy } from '../../../signals/source_fields_merging/strategies'; -import type { BaseSignalHit, SignalSource, SignalSourceHit } from '../../../signals/types'; +import type { BuildReasonMessage } from '../../utils/reason_formatters'; +import { getMergeStrategy } from '../../utils/source_fields_merging/strategies'; +import type { BaseSignalHit, SignalSource, SignalSourceHit } from '../../types'; import { additionalAlertFields, buildAlert } from './build_alert'; import { filterSource } from './filter_source'; import type { CompleteRule, RuleParams } from '../../../rule_schema'; import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; -import { buildRuleNameFromMapping } from '../../../signals/mappings/build_rule_name_from_mapping'; -import { buildSeverityFromMapping } from '../../../signals/mappings/build_severity_from_mapping'; -import { buildRiskScoreFromMapping } from '../../../signals/mappings/build_risk_score_from_mapping'; +import { buildRuleNameFromMapping } from '../../utils/mappings/build_rule_name_from_mapping'; +import { buildSeverityFromMapping } from '../../utils/mappings/build_severity_from_mapping'; +import { buildRiskScoreFromMapping } from '../../utils/mappings/build_risk_score_from_mapping'; import type { BaseFieldsLatest } from '../../../../../../common/detection_engine/schemas/alerts'; import { stripNonEcsFields } from './strip_non_ecs_fields'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/filter_source.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/filter_source.ts index 58e99969e74a8..c0172207c7a60 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/filter_source.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/filter_source.ts @@ -6,7 +6,7 @@ */ import { ALERT_THRESHOLD_RESULT } from '../../../../../../common/field_maps/field_names'; -import type { SignalSourceHit } from '../../../signals/types'; +import type { SignalSourceHit } from '../../types'; export const filterSource = (doc: SignalSourceHit) => { const docSource = doc._source ?? {}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts index ee49980bffac9..aae7501bf3798 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/wrap_hits_factory.ts @@ -9,11 +9,11 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ALERT_UUID } from '@kbn/rule-data-utils'; import type { ConfigType } from '../../../../config'; -import type { SignalSource, SimpleHit } from '../../signals/types'; +import type { SignalSource, SimpleHit } from '../types'; import type { CompleteRule, RuleParams } from '../../rule_schema'; -import { generateId } from '../../signals/utils'; +import { generateId } from '../utils/utils'; import { buildBulkBody } from './utils/build_bulk_body'; -import type { BuildReasonMessage } from '../../signals/reason_formatters'; +import type { BuildReasonMessage } from '../utils/reason_formatters'; import type { BaseFieldsLatest, WrappedFieldsLatest, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts index 796900829d6ea..d85aa18e3b71f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts @@ -11,7 +11,7 @@ import { SERVER_APP_ID } from '../../../../../common/constants'; import type { ThreatRuleParams } from '../../rule_schema'; import { threatRuleParams } from '../../rule_schema'; -import { threatMatchExecutor } from '../../signals/executors/threat_match'; +import { indicatorMatchExecutor } from './indicator_match'; import type { CreateRuleOptions, SecurityAlertType } from '../types'; import { validateIndexPatterns } from '../utils'; @@ -82,7 +82,7 @@ export const createIndicatorMatchAlertType = ( state, } = execOptions; - const result = await threatMatchExecutor({ + const result = await indicatorMatchExecutor({ inputIndex, runtimeMappings, completeRule, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threat_match.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threat_match.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts index 8ebf39867dea4..15f578efbc2bd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threat_match.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/indicator_match.ts @@ -17,13 +17,13 @@ import type { ListClient } from '@kbn/lists-plugin/server'; import type { Filter } from '@kbn/es-query'; import type { RuleRangeTuple, BulkCreate, WrapHits } from '../types'; import type { ITelemetryEventsSender } from '../../../telemetry/sender'; -import { createThreatSignals } from '../threat_mapping/create_threat_signals'; +import { createThreatSignals } from './threat_mapping/create_threat_signals'; import type { CompleteRule, ThreatRuleParams } from '../../rule_schema'; import { withSecuritySpan } from '../../../../utils/with_security_span'; import { DEFAULT_INDICATOR_SOURCE_PATH } from '../../../../../common/constants'; import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; -export const threatMatchExecutor = async ({ +export const indicatorMatchExecutor = async ({ inputIndex, runtimeMappings, completeRule, @@ -60,7 +60,7 @@ export const threatMatchExecutor = async ({ }) => { const ruleParams = completeRule.ruleParams; - return withSecuritySpan('threatMatchExecutor', async () => { + return withSecuritySpan('indicatorMatchExecutor', async () => { return createThreatSignals({ alertId: completeRule.alertId, bulkCreate, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_enrichment.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_enrichment.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts index 18cf4240d0b18..70819f6896861 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_enrichment.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SignalsEnrichment } from '../types'; +import type { SignalsEnrichment } from '../../types'; import type { BuildThreatEnrichmentOptions } from './types'; import { buildThreatMappingFilter } from './build_threat_mapping_filter'; import { getSignalsQueryMapFromThreatIndex } from './get_signals_map_from_threat_index'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.mock.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.mock.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.mock.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_mapping_filter.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_event_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts similarity index 93% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_event_signal.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts index c006ab528b3c5..8fea8412be38a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_event_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts @@ -6,11 +6,11 @@ */ import { buildThreatMappingFilter } from './build_threat_mapping_filter'; -import { getFilter } from '../get_filter'; -import { searchAfterAndBulkCreate } from '../search_after_bulk_create'; -import { buildReasonMessageForThreatMatchAlert } from '../reason_formatters'; +import { getFilter } from '../../utils/get_filter'; +import { searchAfterAndBulkCreate } from '../../utils/search_after_bulk_create'; +import { buildReasonMessageForThreatMatchAlert } from '../../utils/reason_formatters'; import type { CreateEventSignalOptions } from './types'; -import type { SearchAfterAndBulkCreateReturnType } from '../types'; +import type { SearchAfterAndBulkCreateReturnType } from '../../types'; import { getSignalsQueryMapFromThreatIndex } from './get_signals_map_from_threat_index'; import { threatEnrichmentFactory } from './threat_enrichment_factory'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_threat_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts similarity index 91% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_threat_signal.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts index 8773abbdae842..abaac2456cd9b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_threat_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signal.ts @@ -6,11 +6,11 @@ */ import { buildThreatMappingFilter } from './build_threat_mapping_filter'; -import { getFilter } from '../get_filter'; -import { searchAfterAndBulkCreate } from '../search_after_bulk_create'; -import { buildReasonMessageForThreatMatchAlert } from '../reason_formatters'; +import { getFilter } from '../../utils/get_filter'; +import { searchAfterAndBulkCreate } from '../../utils/search_after_bulk_create'; +import { buildReasonMessageForThreatMatchAlert } from '../../utils/reason_formatters'; import type { CreateThreatSignalOptions } from './types'; -import type { SearchAfterAndBulkCreateReturnType } from '../types'; +import type { SearchAfterAndBulkCreateReturnType } from '../../types'; import { buildThreatEnrichment } from './build_threat_enrichment'; export const createThreatSignal = async ({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_threat_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_threat_signals.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts index a73485a4fd375..acfe38eaca34a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/create_threat_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts @@ -16,7 +16,7 @@ import type { } from './types'; import { createThreatSignal } from './create_threat_signal'; import { createEventSignal } from './create_event_signal'; -import type { SearchAfterAndBulkCreateReturnType } from '../types'; +import type { SearchAfterAndBulkCreateReturnType } from '../../types'; import { buildExecutionIntervalValidator, combineConcurrentResults, @@ -26,7 +26,7 @@ import { getAllowedFieldsForTermQuery } from './get_allowed_fields_for_terms_que import { getEventCount, getEventList } from './get_event_count'; import { getMappingFilters } from './get_mapping_filters'; -import { THREAT_PIT_KEEP_ALIVE } from '../../../../../common/cti/constants'; +import { THREAT_PIT_KEEP_ALIVE } from '../../../../../../common/cti/constants'; export const createThreatSignals = async ({ alertId, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.mock.ts similarity index 93% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.mock.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.mock.ts index ef68285669de2..9546fabf70915 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SignalSourceHit } from '../types'; +import type { SignalSourceHit } from '../../types'; import type { ThreatMatchNamedQuery } from './types'; export const getNamedQueryMock = ( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.test.ts index 2658c90720adb..c9e2d7ec7b275 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.test.ts @@ -6,9 +6,9 @@ */ import { get } from 'lodash'; -import { ENRICHMENT_DESTINATION_PATH } from '../../../../../common/constants'; -import { ENRICHMENT_TYPES } from '../../../../../common/cti/constants'; -import type { SignalSourceHit } from '../types'; +import { ENRICHMENT_DESTINATION_PATH } from '../../../../../../common/constants'; +import { ENRICHMENT_TYPES } from '../../../../../../common/cti/constants'; +import type { SignalSourceHit } from '../../types'; import { getThreatListItemMock } from './build_threat_mapping_filter.mock'; import { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.ts index 28f43519f118f..303b7fa9eebfe 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/enrich_signal_threat_matches.ts @@ -6,9 +6,9 @@ */ import { get, isObject } from 'lodash'; -import { ENRICHMENT_TYPES, FEED_NAME_PATH } from '../../../../../common/cti/constants'; +import { ENRICHMENT_TYPES, FEED_NAME_PATH } from '../../../../../../common/cti/constants'; -import type { SignalSourceHit } from '../types'; +import type { SignalSourceHit } from '../../types'; import type { ThreatEnrichment, ThreatListItem, ThreatMatchNamedQuery } from './types'; export const MAX_NUMBER_OF_SIGNAL_MATCHES = 200; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_allowed_fields_for_terms_query.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_allowed_fields_for_terms_query.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_allowed_fields_for_terms_query.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_allowed_fields_for_terms_query.test.ts index b13b5d23278ba..deb182e6860dd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_allowed_fields_for_terms_query.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_allowed_fields_for_terms_query.test.ts @@ -7,7 +7,7 @@ import type { IndicesGetFieldMappingResponse } from '@elastic/elasticsearch/lib/api/types'; import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks'; import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; import { getAllowedFieldForTermQueryFromMapping, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_allowed_fields_for_terms_query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_allowed_fields_for_terms_query.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_allowed_fields_for_terms_query.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_allowed_fields_for_terms_query.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_event_count.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_event_count.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_event_count.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_event_count.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_event_count.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_event_count.ts similarity index 92% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_event_count.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_event_count.ts index c17696fbddf20..a48eae47daa9a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_event_count.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_event_count.ts @@ -7,9 +7,9 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EventCountOptions, EventsOptions, EventDoc } from './types'; -import { getQueryFilter } from '../get_query_filter'; -import { singleSearchAfter } from '../single_search_after'; -import { buildEventsSearchQuery } from '../build_events_query'; +import { getQueryFilter } from '../../utils/get_query_filter'; +import { singleSearchAfter } from '../../utils/single_search_after'; +import { buildEventsSearchQuery } from '../../utils/build_events_query'; export const MAX_PER_PAGE = 9000; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_mapping_filters.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_mapping_filters.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_mapping_filters.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_mapping_filters.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_mapping_filters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_mapping_filters.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_mapping_filters.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_mapping_filters.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.mock.ts similarity index 93% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.mock.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.mock.ts index 9fa23d25f2899..41b479b55d064 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.mock.ts @@ -8,7 +8,7 @@ import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import type { GetThreatListOptions } from './types'; import { getListClientMock } from '@kbn/lists-plugin/server/services/lists/list_client.mock'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; const esClient = elasticsearchServiceMock.createElasticsearchClient(); const ruleExecutionLogger = ruleExecutionLogMock.forExecutors.create(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_signals_map_from_threat_index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_threat_list.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_threat_list.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_threat_list.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_threat_list.ts index 160de278f47e3..50bcf3c63cb0f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_threat_list.ts @@ -6,7 +6,7 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { getQueryFilter } from '../get_query_filter'; +import { getQueryFilter } from '../../utils/get_query_filter'; import type { GetThreatListOptions, ThreatListCountOptions, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/threat_enrichment_factory.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/threat_enrichment_factory.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/threat_enrichment_factory.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/threat_enrichment_factory.test.ts index 3c6bb7d8ee169..ddee331060a9a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/threat_enrichment_factory.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/threat_enrichment_factory.test.ts @@ -7,7 +7,7 @@ import { getThreatList } from './get_threat_list'; import { getNamedQueryMock } from './enrich_signal_threat_matches.mock'; -import type { SignalSourceHit } from '../types'; +import type { SignalSourceHit } from '../../types'; import { threatSearchParamsMock } from './get_signals_map_from_threat_index.mock'; import { threatEnrichmentFactory } from './threat_enrichment_factory'; import { enrichSignalThreatMatchesFromSignalsMap } from './enrich_signal_threat_matches'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/threat_enrichment_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/threat_enrichment_factory.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/threat_enrichment_factory.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/threat_enrichment_factory.ts index 9d8da19f613bb..1bf61512135e0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/threat_enrichment_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/threat_enrichment_factory.ts @@ -6,7 +6,7 @@ */ import type { CreateEventSignalOptions, GetThreatListOptions } from './types'; -import type { SignalSourceHit } from '../types'; +import type { SignalSourceHit } from '../../types'; import { getThreatList } from './get_threat_list'; import { enrichSignalThreatMatchesFromSignalsMap } from './enrich_signal_threat_matches'; import { type SignalsQueryMap } from './get_signals_map_from_threat_index'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts index 63cf588ae43a1..243f67a8d773e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/types.ts @@ -28,16 +28,16 @@ import type { } from '@kbn/alerting-plugin/server'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { Filter } from '@kbn/es-query'; -import type { ITelemetryEventsSender } from '../../../telemetry/sender'; +import type { ITelemetryEventsSender } from '../../../../telemetry/sender'; import type { BulkCreate, RuleRangeTuple, SearchAfterAndBulkCreateReturnType, WrapHits, OverrideBodyQuery, -} from '../types'; -import type { CompleteRule, ThreatRuleParams } from '../../rule_schema'; -import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +} from '../../types'; +import type { CompleteRule, ThreatRuleParams } from '../../../rule_schema'; +import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; export type SortOrderOrUndefined = 'asc' | 'desc' | undefined; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/utils.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/utils.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/utils.test.ts index 57eae75ba4f5c..7554222960203 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/utils.test.ts @@ -5,8 +5,8 @@ * 2.0. */ -import type { SearchAfterAndBulkCreateReturnType } from '../types'; -import { sampleSignalHit } from '../__mocks__/es_results'; +import type { SearchAfterAndBulkCreateReturnType } from '../../types'; +import { sampleSignalHit } from '../../__mocks__/es_results'; import type { ThreatMatchNamedQuery, ThreatTermNamedQuery } from './types'; import { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/utils.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/utils.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/utils.ts index 4e97fd36033d5..dd90e52cddd01 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/utils.ts @@ -9,8 +9,8 @@ import moment from 'moment'; import type { ThreatMapping } from '@kbn/securitysolution-io-ts-alerting-types'; import { get } from 'lodash'; -import type { SearchAfterAndBulkCreateReturnType, SignalSourceHit } from '../types'; -import { parseInterval } from '../utils'; +import type { SearchAfterAndBulkCreateReturnType, SignalSourceHit } from '../../types'; +import { parseInterval } from '../../utils/utils'; import { ThreatMatchQueryType } from './types'; import type { ThreatListItem, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/bulk_create_ml_signals.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/bulk_create_ml_signals.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/bulk_create_ml_signals.ts similarity index 84% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/bulk_create_ml_signals.ts index 7f565036abe3f..25ff5cca03f2e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/bulk_create_ml_signals.ts @@ -13,14 +13,14 @@ import type { AlertInstanceState, RuleExecutorServices, } from '@kbn/alerting-plugin/server'; -import type { GenericBulkCreateResponse } from '../rule_types/factories'; -import type { Anomaly } from '../../machine_learning'; -import type { BulkCreate, WrapHits } from './types'; -import type { CompleteRule, MachineLearningRuleParams } from '../rule_schema'; -import { buildReasonMessageForMlAlert } from './reason_formatters'; -import type { BaseFieldsLatest } from '../../../../common/detection_engine/schemas/alerts'; -import type { IRuleExecutionLogForExecutors } from '../rule_monitoring'; -import { createEnrichEventsFunction } from './enrichments'; +import type { GenericBulkCreateResponse } from '../factories'; +import type { Anomaly } from '../../../machine_learning'; +import type { BulkCreate, WrapHits } from '../types'; +import type { CompleteRule, MachineLearningRuleParams } from '../../rule_schema'; +import { buildReasonMessageForMlAlert } from '../utils/reason_formatters'; +import type { BaseFieldsLatest } from '../../../../../common/detection_engine/schemas/alerts'; +import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +import { createEnrichEventsFunction } from '../utils/enrichments'; interface BulkCreateMlSignalsParams { anomalyHits: Array>; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts index c652de348484f..753e837f08b5f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts @@ -11,7 +11,7 @@ import { SERVER_APP_ID } from '../../../../../common/constants'; import type { MachineLearningRuleParams } from '../../rule_schema'; import { machineLearningRuleParams } from '../../rule_schema'; -import { mlExecutor } from '../../signals/executors/ml'; +import { mlExecutor } from './ml'; import type { CreateRuleOptions, SecurityAlertType } from '../types'; export const createMlAlertType = ( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/find_ml_signals.ts similarity index 90% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/find_ml_signals.ts index fa66548e20503..fdb7317e85bfa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/find_ml_signals.ts @@ -9,8 +9,8 @@ import dateMath from '@kbn/datemath'; import type { KibanaRequest, SavedObjectsClientContract } from '@kbn/core/server'; import type { MlPluginSetup } from '@kbn/ml-plugin/server'; import type { Filter } from '@kbn/es-query'; -import type { AnomalyResults } from '../../machine_learning'; -import { getAnomalies } from '../../machine_learning'; +import type { AnomalyResults } from '../../../machine_learning'; +import { getAnomalies } from '../../../machine_learning'; export const findMlSignals = async ({ ml, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/ml.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/ml.test.ts similarity index 95% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/ml.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/ml.test.ts index 042073005e4a1..d1adcc535c1cc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/ml.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/ml.test.ts @@ -11,14 +11,14 @@ import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { mlExecutor } from './ml'; import { getCompleteRuleMock, getMlRuleParams } from '../../rule_schema/mocks'; import { getListClientMock } from '@kbn/lists-plugin/server/services/lists/list_client.mock'; -import { findMlSignals } from '../find_ml_signals'; -import { bulkCreateMlSignals } from '../bulk_create_ml_signals'; +import { findMlSignals } from './find_ml_signals'; +import { bulkCreateMlSignals } from './bulk_create_ml_signals'; import { mlPluginServerMock } from '@kbn/ml-plugin/server/mocks'; import type { MachineLearningRuleParams } from '../../rule_schema'; import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; -jest.mock('../find_ml_signals'); -jest.mock('../bulk_create_ml_signals'); +jest.mock('./find_ml_signals'); +jest.mock('./bulk_create_ml_signals'); describe('ml_executor', () => { let jobsSummaryMock: jest.Mock; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/ml.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/ml.ts similarity index 95% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/ml.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/ml.ts index 9cd7a6bce13dc..c0fb5401bede8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/ml.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/ml.ts @@ -16,16 +16,16 @@ import type { ListClient } from '@kbn/lists-plugin/server'; import type { Filter } from '@kbn/es-query'; import { isJobStarted } from '../../../../../common/machine_learning/helpers'; import type { CompleteRule, MachineLearningRuleParams } from '../../rule_schema'; -import { bulkCreateMlSignals } from '../bulk_create_ml_signals'; -import { filterEventsAgainstList } from '../filters/filter_events_against_list'; -import { findMlSignals } from '../find_ml_signals'; +import { bulkCreateMlSignals } from './bulk_create_ml_signals'; +import { filterEventsAgainstList } from '../utils/large_list_filters/filter_events_against_list'; +import { findMlSignals } from './find_ml_signals'; import type { BulkCreate, RuleRangeTuple, WrapHits } from '../types'; import { addToSearchAfterReturn, createErrorsFromShard, createSearchAfterReturnType, mergeReturns, -} from '../utils'; +} from '../utils/utils'; import type { SetupPlugins } from '../../../../plugin'; import { withSecuritySpan } from '../../../../utils/with_security_span'; import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/build_new_terms_aggregation.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/build_new_terms_aggregation.ts index e9bf89554941f..93ba7064c6ce3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/build_new_terms_aggregation.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/build_new_terms_aggregation.ts @@ -7,7 +7,7 @@ import type { Moment } from 'moment'; import type { ESSearchResponse } from '@kbn/es-types'; -import type { SignalSource } from '../../signals/types'; +import type { SignalSource } from '../types'; export type RecentTermsAggResult = ESSearchResponse< SignalSource, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts index 64a1f4b093d42..c4525de1b00b3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/create_new_terms_alert_type.ts @@ -12,10 +12,10 @@ import { SERVER_APP_ID } from '../../../../../common/constants'; import type { NewTermsRuleParams } from '../../rule_schema'; import { newTermsRuleParams } from '../../rule_schema'; import type { CreateRuleOptions, SecurityAlertType } from '../types'; -import { singleSearchAfter } from '../../signals/single_search_after'; -import { getFilter } from '../../signals/get_filter'; -import { wrapNewTermsAlerts } from '../factories/utils/wrap_new_terms_alerts'; -import type { EventsAndTerms } from '../factories/utils/wrap_new_terms_alerts'; +import { singleSearchAfter } from '../utils/single_search_after'; +import { getFilter } from '../utils/get_filter'; +import { wrapNewTermsAlerts } from './wrap_new_terms_alerts'; +import type { EventsAndTerms } from './wrap_new_terms_alerts'; import type { DocFetchAggResult, RecentTermsAggResult, @@ -39,8 +39,8 @@ import { addToSearchAfterReturn, createSearchAfterReturnType, getUnprocessedExceptionsWarnings, -} from '../../signals/utils'; -import { createEnrichEventsFunction } from '../../signals/enrichments'; +} from '../utils/utils'; +import { createEnrichEventsFunction } from '../utils/enrichments'; export const createNewTermsAlertType = ( createOptions: CreateRuleOptions diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_new_terms_alerts.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/wrap_new_terms_alerts.test.ts similarity index 93% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_new_terms_alerts.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/wrap_new_terms_alerts.test.ts index 3060deaf712bd..69d0b90b45c29 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_new_terms_alerts.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/wrap_new_terms_alerts.test.ts @@ -6,10 +6,10 @@ */ import { ALERT_UUID } from '@kbn/rule-data-utils'; -import { ALERT_NEW_TERMS } from '../../../../../../common/field_maps/field_names'; -import { getCompleteRuleMock, getNewTermsRuleParams } from '../../../rule_schema/mocks'; -import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; -import { sampleDocNoSortIdWithTimestamp } from '../../../signals/__mocks__/es_results'; +import { ALERT_NEW_TERMS } from '../../../../../common/field_maps/field_names'; +import { getCompleteRuleMock, getNewTermsRuleParams } from '../../rule_schema/mocks'; +import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { sampleDocNoSortIdWithTimestamp } from '../__mocks__/es_results'; import { wrapNewTermsAlerts } from './wrap_new_terms_alerts'; const ruleExecutionLogger = ruleExecutionLogMock.forExecutors.create(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_new_terms_alerts.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/wrap_new_terms_alerts.ts similarity index 77% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_new_terms_alerts.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/wrap_new_terms_alerts.ts index d87bdceb9cecd..424c52273c30a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_new_terms_alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/new_terms/wrap_new_terms_alerts.ts @@ -12,14 +12,14 @@ import type { BaseFieldsLatest, NewTermsFieldsLatest, WrappedFieldsLatest, -} from '../../../../../../common/detection_engine/schemas/alerts'; -import { ALERT_NEW_TERMS } from '../../../../../../common/field_maps/field_names'; -import type { ConfigType } from '../../../../../config'; -import type { CompleteRule, RuleParams } from '../../../rule_schema'; -import { buildReasonMessageForNewTermsAlert } from '../../../signals/reason_formatters'; -import type { SignalSource } from '../../../signals/types'; -import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; -import { buildBulkBody } from './build_bulk_body'; +} from '../../../../../common/detection_engine/schemas/alerts'; +import { ALERT_NEW_TERMS } from '../../../../../common/field_maps/field_names'; +import type { ConfigType } from '../../../../config'; +import type { CompleteRule, RuleParams } from '../../rule_schema'; +import { buildReasonMessageForNewTermsAlert } from '../utils/reason_formatters'; +import type { SignalSource } from '../types'; +import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +import { buildBulkBody } from '../factories/utils/build_bulk_body'; export interface EventsAndTerms { event: estypes.SearchHit; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/__snapshots__/build_group_by_field_aggregation.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/__snapshots__/build_group_by_field_aggregation.test.ts.snap similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/__snapshots__/build_group_by_field_aggregation.test.ts.snap rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/__snapshots__/build_group_by_field_aggregation.test.ts.snap diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/__snapshots__/group_and_bulk_create.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/__snapshots__/group_and_bulk_create.test.ts.snap similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/__snapshots__/group_and_bulk_create.test.ts.snap rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/__snapshots__/group_and_bulk_create.test.ts.snap diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/build_group_by_field_aggregation.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/build_group_by_field_aggregation.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/build_group_by_field_aggregation.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/build_group_by_field_aggregation.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/build_group_by_field_aggregation.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/build_group_by_field_aggregation.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/build_group_by_field_aggregation.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/build_group_by_field_aggregation.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_with_suppression.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/bulk_create_with_suppression.ts similarity index 91% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_with_suppression.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/bulk_create_with_suppression.ts index fb49a498805f9..88af364c732a4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_with_suppression.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/bulk_create_with_suppression.ts @@ -13,14 +13,14 @@ import type { AlertWithCommonFieldsLatest, SuppressionFieldsLatest, } from '@kbn/rule-registry-plugin/common/schemas'; -import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; -import { makeFloatString } from '../../signals/utils'; +import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; +import { makeFloatString } from '../../utils/utils'; import type { BaseFieldsLatest, WrappedFieldsLatest, -} from '../../../../../common/detection_engine/schemas/alerts'; -import type { RuleServices } from '../../signals/types'; -import { createEnrichEventsFunction } from '../../signals/enrichments'; +} from '../../../../../../common/detection_engine/schemas/alerts'; +import type { RuleServices } from '../../types'; +import { createEnrichEventsFunction } from '../../utils/enrichments'; export interface GenericBulkCreateResponse { success: boolean; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/group_and_bulk_create.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/group_and_bulk_create.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/group_and_bulk_create.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/group_and_bulk_create.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/group_and_bulk_create.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/group_and_bulk_create.ts similarity index 83% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/group_and_bulk_create.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/group_and_bulk_create.ts index 5e67b4c01f6ce..99f1901aad9f8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/alert_suppression/group_and_bulk_create.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/group_and_bulk_create.ts @@ -9,25 +9,55 @@ import type moment from 'moment'; import type * as estypes from '@elastic/elasticsearch/lib/api/types'; -import { withSecuritySpan } from '../../../../utils/with_security_span'; -import { buildTimeRangeFilter } from '../build_events_query'; +import type { ESSearchResponse } from '@kbn/es-types'; + +import { withSecuritySpan } from '../../../../../utils/with_security_span'; +import { buildTimeRangeFilter } from '../../utils/build_events_query'; import type { - EventGroupingMultiBucketAggregationResult, - GroupAndBulkCreateParams, - GroupAndBulkCreateReturnType, -} from '../types'; -import { addToSearchAfterReturn, getUnprocessedExceptionsWarnings } from '../utils'; -import type { SuppressionBuckets } from '../../rule_types/factories/utils/wrap_suppressed_alerts'; -import { wrapSuppressedAlerts } from '../../rule_types/factories/utils/wrap_suppressed_alerts'; + RuleServices, + RunOpts, + SearchAfterAndBulkCreateReturnType, + SignalSource, +} from '../../types'; +import { addToSearchAfterReturn, getUnprocessedExceptionsWarnings } from '../../utils/utils'; +import type { SuppressionBuckets } from './wrap_suppressed_alerts'; +import { wrapSuppressedAlerts } from './wrap_suppressed_alerts'; import { buildGroupByFieldAggregation } from './build_group_by_field_aggregation'; -import { singleSearchAfter } from '../single_search_after'; -import { bulkCreateWithSuppression } from '../../rule_types/factories/bulk_create_with_suppression'; +import { singleSearchAfter } from '../../utils/single_search_after'; +import { bulkCreateWithSuppression } from './bulk_create_with_suppression'; +import type { UnifiedQueryRuleParams } from '../../../rule_schema'; +import type { BuildReasonMessage } from '../../utils/reason_formatters'; export interface BucketHistory { key: Record; endDate: string; } +export interface GroupAndBulkCreateParams { + runOpts: RunOpts; + services: RuleServices; + spaceId: string; + filter: estypes.QueryDslQueryContainer; + buildReasonMessage: BuildReasonMessage; + bucketHistory?: BucketHistory[]; + groupByFields: string[]; +} + +export interface GroupAndBulkCreateReturnType extends SearchAfterAndBulkCreateReturnType { + state: { + suppressionGroupHistory: BucketHistory[]; + }; +} + +type EventGroupingMultiBucketAggregationResult = ESSearchResponse< + SignalSource, + { + body: { + aggregations: ReturnType; + }; + } +>; + /** * Builds a filter that excludes documents from existing buckets. */ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_suppressed_alerts.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/wrap_suppressed_alerts.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_suppressed_alerts.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/wrap_suppressed_alerts.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_suppressed_alerts.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/wrap_suppressed_alerts.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_suppressed_alerts.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/wrap_suppressed_alerts.ts index 581d6a256723e..42fe0954a1847 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/wrap_suppressed_alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/alert_suppression/wrap_suppressed_alerts.ts @@ -23,9 +23,9 @@ import type { import type { ConfigType } from '../../../../../config'; import type { CompleteRule, RuleParams } from '../../../rule_schema'; import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; -import type { SignalSource } from '../../../signals/types'; -import { buildBulkBody } from './build_bulk_body'; -import type { BuildReasonMessage } from '../../../signals/reason_formatters'; +import type { SignalSource } from '../../types'; +import { buildBulkBody } from '../../factories/utils/build_bulk_body'; +import type { BuildReasonMessage } from '../../utils/reason_formatters'; export interface SuppressionBuckets { event: estypes.SearchHit; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts index 0478c4d49c1ba..4d6b3120488fa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts @@ -14,13 +14,13 @@ import { createSecurityRuleTypeWrapper } from '../create_security_rule_type_wrap import { createMockConfig } from '../../routes/__mocks__'; import { createMockTelemetryEventsSender } from '../../../telemetry/__mocks__'; import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; -import { sampleDocNoSortId } from '../../signals/__mocks__/es_results'; +import { sampleDocNoSortId } from '../__mocks__/es_results'; import { getQueryRuleParams } from '../../rule_schema/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; import { QUERY_RULE_TYPE_ID } from '@kbn/securitysolution-rules'; -jest.mock('../../signals/utils', () => ({ - ...jest.requireActual('../../signals/utils'), +jest.mock('../utils/utils', () => ({ + ...jest.requireActual('../utils/utils'), getExceptions: () => [], })); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts index 89a43f896a4d9..2aa3a708c672a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts @@ -8,10 +8,10 @@ import { validateNonExact } from '@kbn/securitysolution-io-ts-utils'; import { SERVER_APP_ID } from '../../../../../common/constants'; -import type { BucketHistory } from '../../signals/alert_suppression/group_and_bulk_create'; +import type { BucketHistory } from './alert_suppression/group_and_bulk_create'; import type { UnifiedQueryRuleParams } from '../../rule_schema'; import { unifiedQueryRuleParams } from '../../rule_schema'; -import { queryExecutor } from '../../signals/executors/query'; +import { queryExecutor } from './query'; import type { CreateQueryRuleOptions, SecurityAlertType } from '../types'; import { validateIndexPatterns } from '../utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts similarity index 90% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts index 7c3dc31b742ae..52157c2f64a94 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts @@ -13,18 +13,18 @@ import type { import { firstValueFrom } from 'rxjs'; import type { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; -import { getFilter } from '../get_filter'; -import type { BucketHistory } from '../alert_suppression/group_and_bulk_create'; -import { groupAndBulkCreate } from '../alert_suppression/group_and_bulk_create'; -import { searchAfterAndBulkCreate } from '../search_after_bulk_create'; +import { getFilter } from '../utils/get_filter'; +import type { BucketHistory } from './alert_suppression/group_and_bulk_create'; +import { groupAndBulkCreate } from './alert_suppression/group_and_bulk_create'; +import { searchAfterAndBulkCreate } from '../utils/search_after_bulk_create'; import type { ITelemetryEventsSender } from '../../../telemetry/sender'; import type { UnifiedQueryRuleParams } from '../../rule_schema'; import type { ExperimentalFeatures } from '../../../../../common/experimental_features'; -import { buildReasonMessageForQueryAlert } from '../reason_formatters'; +import { buildReasonMessageForQueryAlert } from '../utils/reason_formatters'; import { withSecuritySpan } from '../../../../utils/with_security_span'; import { scheduleNotificationResponseActions } from '../../rule_response_actions/schedule_notification_response_actions'; import type { SetupPlugins } from '../../../../plugin_contract'; -import type { RunOpts } from '../../rule_types/types'; +import type { RunOpts } from '../types'; export const queryExecutor = async ({ runOpts, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/README.md b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/README.md similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/README.md rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/README.md diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_data_view.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_data_view.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_data_view.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_data_view.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_data_view.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_data_view.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_data_view.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_data_view.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_exceptions_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_exceptions_list.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_exceptions_list.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_exceptions_list.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_exceptions_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_exceptions_list.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_exceptions_list.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_exceptions_list.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_references.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_references.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_references.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_references.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_references.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_references.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_references.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_references.ts index 91ceb32edfe35..066aa06864e41 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/extract_references.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/extract_references.ts @@ -10,7 +10,7 @@ import type { RuleParamsAndRefs } from '@kbn/alerting-plugin/server'; import type { RuleParams } from '../../rule_schema'; -import { isMachineLearningParams } from '../utils'; +import { isMachineLearningParams } from '../utils/utils'; import { extractExceptionsList } from './extract_exceptions_list'; import { extractDataView } from './extract_data_view'; @@ -30,7 +30,7 @@ import { extractDataView } from './extract_data_view'; * Optionally you can remove any parameters you do not want to store within the Saved Object here: * const paramsWithoutSavedObjectReferences = { removeParam, ...otherParams }; * - * If you do remove params, then update the types in: security_solution/server/lib/detection_engine/signals/types.ts + * If you do remove params, then update the types in: security_solution/server/lib/detection_engine/rule_types/types.ts * to use an omit for the functions of "isAlertExecutor" and "SignalRuleAlertTypeDefinition" * @param logger Kibana injected logger * @param params The params of the base rule(s). diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_data_view.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_data_view.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_data_view.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_data_view.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_data_view.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_data_view.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_data_view.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_data_view.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_exceptions_list.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_exceptions_list.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_exceptions_list.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_exceptions_list.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_references.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_references.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_references.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_references.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_references.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_references.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_references.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_references.ts index 40ad3cf3678a9..876e329734f8c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_references.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/inject_references.ts @@ -7,7 +7,7 @@ import type { Logger, SavedObjectReference } from '@kbn/core/server'; import type { RuleParams } from '../../rule_schema'; -import { isMachineLearningParams } from '../utils'; +import { isMachineLearningParams } from '../utils/utils'; import { injectExceptionsReferences } from './inject_exceptions_list'; import { injectDataViewReferences } from './inject_data_view'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/constants.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/constants.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/constants.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/constants.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_name_pattern_for_exception_list.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_data_view.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_data_view.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_data_view.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_data_view.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_data_view.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_data_view.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_data_view.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_data_view.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/get_saved_object_reference_for_exceptions_list.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_missing_saved_object_error.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/log_missing_saved_object_error.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_missing_saved_object_error.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/log_missing_saved_object_error.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_missing_saved_object_error.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/log_missing_saved_object_error.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_missing_saved_object_error.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/saved_object_references/utils/log_missing_saved_object_error.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/__snapshots__/get_threshold_signal_history.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/__snapshots__/get_threshold_signal_history.test.ts.snap similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/__snapshots__/get_threshold_signal_history.test.ts.snap rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/__snapshots__/get_threshold_signal_history.test.ts.snap diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_signal_history.test.ts similarity index 93% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_signal_history.test.ts index 8196fa229c65c..5d36e6ebad2d9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_signal_history.test.ts @@ -6,7 +6,7 @@ */ import { ALERT_ORIGINAL_TIME } from '../../../../../common/field_maps/field_names'; -import { sampleThresholdAlert } from '../../rule_types/__mocks__/threshold'; +import { sampleThresholdAlert } from '../__mocks__/threshold'; import { buildThresholdSignalHistory } from './build_signal_history'; describe('buildSignalHistory', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_signal_history.ts similarity index 91% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_signal_history.ts index 8497b94397d9b..e6390fe7f67ea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_signal_history.ts @@ -9,8 +9,10 @@ import type { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey' import { ALERT_RULE_PARAMETERS } from '@kbn/rule-data-utils'; import { ALERT_ORIGINAL_TIME } from '../../../../../common/field_maps/field_names'; -import type { SimpleHit, ThresholdSignalHistory } from '../types'; -import { getThresholdTermsHash, isWrappedDetectionAlert, isWrappedSignalHit } from '../utils'; +import type { SimpleHit } from '../types'; +import type { ThresholdSignalHistory } from './types'; +import { getThresholdTermsHash } from './utils'; +import { isWrappedDetectionAlert, isWrappedSignalHit } from '../utils/utils'; interface GetThresholdSignalHistoryParams { alerts: Array>; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_threshold_aggregation.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_threshold_aggregation.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_threshold_aggregation.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_threshold_aggregation.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_threshold_aggregation.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_threshold_aggregation.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_threshold_aggregation.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/build_threshold_aggregation.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/bulk_create_threshold_signals.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/bulk_create_threshold_signals.test.ts index 1fa0baaedfa13..1e709b9b47017 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/bulk_create_threshold_signals.test.ts @@ -6,7 +6,7 @@ */ import type { ThresholdNormalized } from '../../../../../common/detection_engine/rule_schema'; -import { calculateThresholdSignalUuid } from '../utils'; +import { calculateThresholdSignalUuid } from './utils'; import { getTransformedHits } from './bulk_create_threshold_signals'; describe('transformThresholdNormalizedResultsToEcs', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/bulk_create_threshold_signals.ts similarity index 88% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/bulk_create_threshold_signals.ts index 22ebcf8c1ced0..1bef127097e60 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/bulk_create_threshold_signals.ts @@ -13,14 +13,14 @@ import type { RuleExecutorServices, } from '@kbn/alerting-plugin/server'; import type { ThresholdNormalized } from '../../../../../common/detection_engine/rule_schema'; -import type { GenericBulkCreateResponse } from '../../rule_types/factories/bulk_create_factory'; -import { calculateThresholdSignalUuid } from '../utils'; -import { buildReasonMessageForThresholdAlert } from '../reason_formatters'; -import type { ThresholdSignalHistory, BulkCreate, WrapHits } from '../types'; +import type { GenericBulkCreateResponse } from '../factories/bulk_create_factory'; +import { calculateThresholdSignalUuid } from './utils'; +import { buildReasonMessageForThresholdAlert } from '../utils/reason_formatters'; +import type { ThresholdSignalHistory, ThresholdBucket } from './types'; +import type { BulkCreate, WrapHits } from '../types'; import type { CompleteRule, ThresholdRuleParams } from '../../rule_schema'; import type { BaseFieldsLatest } from '../../../../../common/detection_engine/schemas/alerts'; -import type { ThresholdBucket } from './types'; -import { createEnrichEventsFunction } from '../enrichments'; +import { createEnrichEventsFunction } from '../utils/enrichments'; import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; interface BulkCreateThresholdSignalsParams { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts index b465abed15977..273c3abd3966f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/create_threshold_alert_type.ts @@ -11,8 +11,8 @@ import { SERVER_APP_ID } from '../../../../../common/constants'; import type { ThresholdRuleParams } from '../../rule_schema'; import { thresholdRuleParams } from '../../rule_schema'; -import { thresholdExecutor } from '../../signals/executors/threshold'; -import type { ThresholdAlertState } from '../../signals/types'; +import { thresholdExecutor } from './threshold'; +import type { ThresholdAlertState } from './types'; import type { CreateRuleOptions, SecurityAlertType } from '../types'; import { validateIndexPatterns } from '../utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/find_threshold_signals.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/find_threshold_signals.test.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/find_threshold_signals.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/find_threshold_signals.test.ts index 970010a3bce43..ab19edade87f7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/find_threshold_signals.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/find_threshold_signals.test.ts @@ -8,13 +8,13 @@ import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks'; import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { sampleEmptyDocSearchResults } from '../__mocks__/es_results'; -import * as single_search_after from '../single_search_after'; +import * as single_search_after from '../utils/single_search_after'; import { findThresholdSignals } from './find_threshold_signals'; import { TIMESTAMP } from '@kbn/rule-data-utils'; import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; -import { buildTimestampRuntimeMapping } from '../../rule_types/utils'; -import { TIMESTAMP_RUNTIME_FIELD } from '../../rule_types/constants'; -import { getQueryFilter } from '../get_query_filter'; +import { buildTimestampRuntimeMapping } from '../utils'; +import { TIMESTAMP_RUNTIME_FIELD } from '../constants'; +import { getQueryFilter } from '../utils/get_query_filter'; import type { ESBoolQuery } from '../../../../../common/typed_json'; const mockSingleSearchAfter = jest.fn(async () => ({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/find_threshold_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/find_threshold_signals.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/find_threshold_signals.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/find_threshold_signals.ts index dba72e0560734..758fe7b161d68 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/find_threshold_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/find_threshold_signals.ts @@ -18,7 +18,7 @@ import type { ThresholdNormalized, TimestampOverride, } from '../../../../../common/detection_engine/rule_schema'; -import { singleSearchAfter } from '../single_search_after'; +import { singleSearchAfter } from '../utils/single_search_after'; import { buildThresholdMultiBucketAggregation, buildThresholdSingleBucketAggregation, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_bucket_filters.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_bucket_filters.test.ts index b38351751a717..299810c169f89 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_bucket_filters.test.ts @@ -6,7 +6,7 @@ */ import { TIMESTAMP } from '@kbn/rule-data-utils'; -import { sampleThresholdSignalHistory } from '../__mocks__/threshold_signal_history.mock'; +import { sampleThresholdSignalHistory } from '../__mocks__/threshold'; import { getThresholdBucketFilters } from './get_threshold_bucket_filters'; describe('getThresholdBucketFilters', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_bucket_filters.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_bucket_filters.ts index dfd61e307bd43..7bb04a8efa5b1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_bucket_filters.ts @@ -7,7 +7,7 @@ import type { Filter } from '@kbn/es-query'; import type { ESFilter } from '@kbn/es-types'; -import type { ThresholdSignalHistory, ThresholdSignalHistoryRecord } from '../types'; +import type { ThresholdSignalHistory, ThresholdSignalHistoryRecord } from './types'; /* * Returns a filter to exclude events that have already been included in a diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_signal_history.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_signal_history.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_signal_history.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_signal_history.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_signal_history.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_signal_history.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_signal_history.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_signal_history.ts index 4826cd574a906..157300796a8ee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_signal_history.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/get_threshold_signal_history.ts @@ -8,9 +8,9 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { IRuleDataReader } from '@kbn/rule-registry-plugin/server'; import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; -import type { ThresholdSignalHistory } from '../types'; +import type { ThresholdSignalHistory } from './types'; import { buildThresholdSignalHistory } from './build_signal_history'; -import { createErrorsFromShard } from '../utils'; +import { createErrorsFromShard } from '../utils/utils'; interface GetThresholdSignalHistoryParams { from: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts index 0e780d9709ab8..2a4f54d23271e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.test.ts @@ -13,7 +13,7 @@ import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { thresholdExecutor } from './threshold'; import { getThresholdRuleParams, getCompleteRuleMock } from '../../rule_schema/mocks'; import { sampleEmptyAggsSearchResults } from '../__mocks__/es_results'; -import { getThresholdTermsHash } from '../utils'; +import { getThresholdTermsHash } from './utils'; import type { ThresholdRuleParams } from '../../rule_schema'; import { createRuleDataClientMock } from '@kbn/rule-registry-plugin/server/rule_data_client/rule_data_client.mock'; import { TIMESTAMP } from '@kbn/rule-data-utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts similarity index 91% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts index 515caf5dcd5e1..670b3e5011a29 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts @@ -17,27 +17,26 @@ import type { import type { IRuleDataReader } from '@kbn/rule-registry-plugin/server'; import type { Filter } from '@kbn/es-query'; import type { CompleteRule, ThresholdRuleParams } from '../../rule_schema'; -import { getFilter } from '../get_filter'; -import { - bulkCreateThresholdSignals, - findThresholdSignals, - getThresholdBucketFilters, - getThresholdSignalHistory, -} from '../threshold'; +import { getFilter } from '../utils/get_filter'; +import { bulkCreateThresholdSignals } from './bulk_create_threshold_signals'; +import { findThresholdSignals } from './find_threshold_signals'; +import { getThresholdBucketFilters } from './get_threshold_bucket_filters'; +import { getThresholdSignalHistory } from './get_threshold_signal_history'; + import type { BulkCreate, RuleRangeTuple, SearchAfterAndBulkCreateReturnType, - ThresholdAlertState, WrapHits, } from '../types'; +import type { ThresholdAlertState } from './types'; import { addToSearchAfterReturn, createSearchAfterReturnType, getUnprocessedExceptionsWarnings, -} from '../utils'; +} from '../utils/utils'; import { withSecuritySpan } from '../../../../utils/with_security_span'; -import { buildThresholdSignalHistory } from '../threshold/build_signal_history'; +import { buildThresholdSignalHistory } from './build_signal_history'; import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; export const thresholdExecutor = async ({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/types.ts similarity index 66% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/types.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/types.ts index d6a68833ed263..14e244000a30d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/types.ts @@ -12,7 +12,9 @@ import type { AggregationsMinAggregate, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ESSearchResponse } from '@kbn/es-types'; +import type { RuleTypeState } from '@kbn/alerting-plugin/server'; import type { SignalSource } from '../types'; +import type { SearchTypes } from '../../../../../common/detection_engine/types'; import type { buildThresholdMultiBucketAggregation, buildThresholdSingleBucketAggregation, @@ -44,3 +46,33 @@ export type ThresholdSingleBucketAggregationResult = ESSearchResponse< export type ThresholdCompositeBucket = AggregationsCompositeBucket & ThresholdLeafAggregates; export type ThresholdBucket = ThresholdCompositeBucket; + +export interface ThresholdResult { + terms?: Array<{ + field: string; + value: string; + }>; + cardinality?: Array<{ + field: string; + value: number; + }>; + count: number; + from: string; +} + +export interface ThresholdSignalHistoryRecord { + terms: Array<{ + field?: string; + value: SearchTypes; + }>; + lastSignalTimestamp: number; +} + +export interface ThresholdSignalHistory { + [hash: string]: ThresholdSignalHistoryRecord; +} + +export interface ThresholdAlertState extends RuleTypeState { + initialized: boolean; + signalHistory: ThresholdSignalHistory; +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/utils.test.ts new file mode 100644 index 0000000000000..0022e88217f8b --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/utils.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { calculateThresholdSignalUuid } from './utils'; + +describe('calculateThresholdSignalUuid', () => { + it('should generate a uuid without key', () => { + const startedAt = new Date('2020-12-17T16:27:00Z'); + const signalUuid = calculateThresholdSignalUuid('abcd', startedAt, ['agent.name']); + expect(signalUuid).toEqual('a4832768-a379-583a-b1a2-e2ce2ad9e6e9'); + }); + + it('should generate a uuid with key', () => { + const startedAt = new Date('2019-11-18T13:32:00Z'); + const signalUuid = calculateThresholdSignalUuid('abcd', startedAt, ['host.ip'], '1.2.3.4'); + expect(signalUuid).toEqual('ee8870dc-45ff-5e6c-a2f9-80886651ce03'); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/utils.ts new file mode 100644 index 0000000000000..1c4f85e250a1f --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/utils.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createHash } from 'crypto'; +import { v5 as uuidv5 } from 'uuid'; +import type { + ThresholdNormalized, + ThresholdWithCardinality, +} from '../../../../../common/detection_engine/rule_schema'; + +export const shouldFilterByCardinality = ( + threshold: ThresholdNormalized +): threshold is ThresholdWithCardinality => !!threshold.cardinality?.length; + +export const calculateThresholdSignalUuid = ( + ruleId: string, + startedAt: Date, + thresholdFields: string[], + key?: string +): string => { + // used to generate stable Threshold Signals ID when run with the same params + const NAMESPACE_ID = '0684ec03-7201-4ee0-8ee0-3a3f6b2479b2'; + + const startedAtString = startedAt.toISOString(); + const keyString = key ?? ''; + const baseString = `${ruleId}${startedAtString}${thresholdFields.join(',')}${keyString}`; + + return uuidv5(baseString, NAMESPACE_ID); +}; + +export const getThresholdTermsHash = ( + terms: Array<{ + field: string; + value: string; + }> +): string => { + return createHash('sha256') + .update( + terms + .sort((term1, term2) => (term1.field > term2.field ? 1 : -1)) + .map((term) => { + return `${term.field}:${term.value}`; + }) + .join(',') + ) + .digest('hex'); +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts index 614236391d041..36ac78f2f74d5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts @@ -13,13 +13,15 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { QUERY_RULE_TYPE_ID, SAVED_QUERY_RULE_TYPE_ID } from '@kbn/securitysolution-rules'; -import type { RuleExecutorOptions, RuleType } from '@kbn/alerting-plugin/server'; import type { - AlertInstanceContext, - AlertInstanceState, + RuleExecutorOptions, + RuleType, RuleTypeState, - WithoutReservedActionGroups, -} from '@kbn/alerting-plugin/common'; + AlertInstanceState, + AlertInstanceContext, + RuleExecutorServices, +} from '@kbn/alerting-plugin/server'; +import type { WithoutReservedActionGroups } from '@kbn/alerting-plugin/common'; import type { ListClient } from '@kbn/lists-plugin/server'; import type { PersistenceServices, @@ -27,23 +29,37 @@ import type { IRuleDataReader, SuppressedAlertService, } from '@kbn/rule-registry-plugin/server'; +import type { EcsFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map'; +import type { TypeOfFieldMap } from '@kbn/rule-registry-plugin/common/field_map'; import type { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; - import type { Filter } from '@kbn/es-query'; + import type { ConfigType } from '../../../config'; import type { SetupPlugins } from '../../../plugin'; import type { CompleteRule, RuleParams } from '../rule_schema'; -import type { - BulkCreate, - SearchAfterAndBulkCreateReturnType, - WrapHits, - WrapSequences, -} from '../signals/types'; import type { ExperimentalFeatures } from '../../../../common/experimental_features'; import type { ITelemetryEventsSender } from '../../telemetry/sender'; import type { IRuleExecutionLogForExecutors, IRuleExecutionLogService } from '../rule_monitoring'; import type { RefreshTypes } from '../types'; +import type { Status } from '../../../../common/detection_engine/schemas/common/schemas'; +import type { + BaseHit, + RuleAlertAction, + SearchTypes, + EqlSequence, +} from '../../../../common/detection_engine/types'; +import type { GenericBulkCreateResponse } from './factories'; +import type { BuildReasonMessage } from './utils/reason_formatters'; +import type { + BaseFieldsLatest, + DetectionAlert, + WrappedFieldsLatest, +} from '../../../../common/detection_engine/schemas/alerts'; +import type { RuleResponse } from '../../../../common/detection_engine/rule_schema'; +import type { EnrichEvents } from './utils/enrichments/types'; +import type { ThresholdResult } from './threshold/types'; + export interface SecurityAlertTypeReturnValue { bulkCreateTimes: string[]; enrichmentTimes: string[]; @@ -147,3 +163,223 @@ export interface CreateQueryRuleOptions id: typeof QUERY_RULE_TYPE_ID | typeof SAVED_QUERY_RULE_TYPE_ID; name: 'Custom Query Rule' | 'Saved Query Rule'; } + +export interface RuleRangeTuple { + to: moment.Moment; + from: moment.Moment; + maxSignals: number; +} + +/** + * SignalSource is being used as both a type for documents that match detection engine queries as well as + * for queries that could be on top of signals. In cases where it is matched against detection engine queries, + * '@timestamp' might not be there since it is not required and we have timestamp override capabilities. Also + * the signal addition object, "signal?: {" will not be there unless it's a conflicting field when we are running + * queries on events. + * + * For cases where we are running queries against signals (signals on signals) "@timestamp" should always be there + * and the "signal?: {" sub-object should always be there. + */ +export interface SignalSource { + [key: string]: SearchTypes; + '@timestamp'?: string; + signal?: { + /** + * "parent" is deprecated: new signals should populate "parents" instead. Both are optional + * until all signals with parent are gone and we can safely remove it. + * @deprecated Use parents instead + */ + parent?: Ancestor; + parents?: Ancestor[]; + ancestors: Ancestor[]; + group?: { + id: string; + index?: number; + }; + rule: { + id: string; + description?: string; + false_positives?: string[]; + immutable?: boolean; + }; + /** signal.depth was introduced in 7.10 and pre-7.10 signals do not have it. */ + depth?: number; + original_time?: string; + /** signal.reason was introduced in 7.15 and pre-7.15 signals do not have it. */ + reason?: string; + status?: string; + threshold_result?: ThresholdResult; + }; + kibana?: SearchTypes; +} + +export interface BulkItem { + create?: { + _index: string; + _type?: string; + _id: string; + _version: number; + result?: string; + _shards?: { + total: number; + successful: number; + failed: number; + }; + _seq_no?: number; + _primary_term?: number; + status: number; + error?: { + type: string; + reason: string; + index_uuid?: string; + shard: string; + index: string; + }; + }; +} + +export interface BulkResponse { + took: number; + errors: boolean; + items: BulkItem[]; +} + +export type EventHit = Exclude, '@timestamp'> & { + '@timestamp': string; + [key: string]: SearchTypes; +}; +export type WrappedEventHit = BaseHit; + +export type SignalSearchResponse< + TAggregations = Record +> = estypes.SearchResponse; +export type SignalSourceHit = estypes.SearchHit; +export type AlertSourceHit = estypes.SearchHit; +export type WrappedSignalHit = BaseHit; +export type BaseSignalHit = estypes.SearchHit; + +export interface Ancestor { + rule?: string; + id: string; + type: string; + index: string; + depth: number; +} + +export interface Signal { + _meta?: { + version: number; + }; + rule: RuleResponse; + /** + * @deprecated Use "parents" instead of "parent" + */ + parent?: Ancestor; + parents: Ancestor[]; + ancestors: Ancestor[]; + group?: { + id: string; + index?: number; + }; + original_time?: string; + original_event?: SearchTypes; + reason?: string; + status: Status; + threshold_result?: ThresholdResult; + original_signal?: SearchTypes; + depth: number; +} + +export interface SignalHit { + '@timestamp': string; + event: object; + signal: Signal; + [key: string]: SearchTypes; +} + +export interface AlertAttributes { + actions: RuleAlertAction[]; + alertTypeId: string; + enabled: boolean; + name: string; + tags: string[]; + createdBy: string; + createdAt: string; + updatedBy: string; + schedule: { + interval: string; + }; + throttle: string; + params: T; +} + +export type BulkResponseErrorAggregation = Record; + +export type SignalsEnrichment = (signals: SignalSourceHit[]) => Promise; + +export type BulkCreate = ( + docs: Array>, + maxAlerts?: number, + enrichEvents?: EnrichEvents +) => Promise>; + +export type SimpleHit = BaseHit<{ '@timestamp'?: string }>; + +export type WrapHits = ( + hits: Array>, + buildReasonMessage: BuildReasonMessage +) => Array>; + +export type WrapSequences = ( + sequences: Array>, + buildReasonMessage: BuildReasonMessage +) => Array>; + +export type RuleServices = RuleExecutorServices< + AlertInstanceState, + AlertInstanceContext, + 'default' +>; +export interface SearchAfterAndBulkCreateParams { + tuple: { + to: moment.Moment; + from: moment.Moment; + maxSignals: number; + }; + services: RuleServices; + listClient: ListClient; + exceptionsList: ExceptionListItemSchema[]; + ruleExecutionLogger: IRuleExecutionLogForExecutors; + eventsTelemetry: ITelemetryEventsSender | undefined; + inputIndexPattern: string[]; + pageSize: number; + filter: estypes.QueryDslQueryContainer; + buildReasonMessage: BuildReasonMessage; + enrichment?: SignalsEnrichment; + bulkCreate: BulkCreate; + wrapHits: WrapHits; + trackTotalHits?: boolean; + sortOrder?: estypes.SortOrder; + runtimeMappings: estypes.MappingRuntimeFields | undefined; + primaryTimestamp: string; + secondaryTimestamp?: string; +} + +export interface SearchAfterAndBulkCreateReturnType { + success: boolean; + warning: boolean; + searchAfterTimes: string[]; + enrichmentTimes: string[]; + bulkCreateTimes: string[]; + lastLookBackDate: Date | null | undefined; + createdSignalsCount: number; + createdSignals: unknown[]; + errors: string[]; + warningMessages: string[]; +} + +// the new fields can be added later if needed +export interface OverrideBodyQuery { + _source?: estypes.SearchSourceConfig; + fields?: estypes.Fields; +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/build_events_query.test.ts similarity index 51% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/build_events_query.test.ts index 8aa51719a69bb..03ee439c2c969 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/build_events_query.test.ts @@ -5,19 +5,7 @@ * 2.0. */ -import { buildEqlSearchRequest, buildEventsSearchQuery } from './build_events_query'; -import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; -import { getListClientMock } from '@kbn/lists-plugin/server/services/lists/list_client.mock'; -import { buildExceptionFilter } from '@kbn/lists-plugin/server/services/exception_lists'; - -const emptyFilter = { - bool: { - must: [], - filter: [], - should: [], - must_not: [], - }, -}; +import { buildEventsSearchQuery } from './build_events_query'; describe('create_signals', () => { test('it builds a now-5m up to today filter', () => { @@ -588,416 +576,4 @@ describe('create_signals', () => { }, }); }); - - describe('buildEqlSearchRequest', () => { - test('should build a basic request with time range', () => { - const request = buildEqlSearchRequest({ - query: 'process where true', - index: ['testindex1', 'testindex2'], - from: 'now-5m', - to: 'now', - size: 100, - filters: undefined, - primaryTimestamp: '@timestamp', - secondaryTimestamp: undefined, - runtimeMappings: undefined, - eventCategoryOverride: undefined, - exceptionFilter: undefined, - }); - expect(request).toEqual({ - allow_no_indices: true, - index: ['testindex1', 'testindex2'], - body: { - size: 100, - query: 'process where true', - runtime_mappings: undefined, - filter: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: 'now-5m', - lte: 'now', - format: 'strict_date_optional_time', - }, - }, - }, - emptyFilter, - ], - }, - }, - fields: [ - { - field: '*', - include_unmapped: true, - }, - { - field: '@timestamp', - format: 'strict_date_optional_time', - }, - ], - }, - }); - }); - - test('should build a request with timestamp and event category overrides', () => { - const request = buildEqlSearchRequest({ - query: 'process where true', - index: ['testindex1', 'testindex2'], - from: 'now-5m', - to: 'now', - size: 100, - filters: undefined, - primaryTimestamp: 'event.ingested', - secondaryTimestamp: '@timestamp', - runtimeMappings: undefined, - eventCategoryOverride: 'event.other_category', - timestampField: undefined, - exceptionFilter: undefined, - }); - expect(request).toEqual({ - allow_no_indices: true, - index: ['testindex1', 'testindex2'], - body: { - event_category_field: 'event.other_category', - size: 100, - query: 'process where true', - runtime_mappings: undefined, - filter: { - bool: { - filter: [ - { - bool: { - minimum_should_match: 1, - should: [ - { - range: { - 'event.ingested': { - lte: 'now', - gte: 'now-5m', - format: 'strict_date_optional_time', - }, - }, - }, - { - bool: { - filter: [ - { - range: { - '@timestamp': { - lte: 'now', - gte: 'now-5m', - format: 'strict_date_optional_time', - }, - }, - }, - { - bool: { - must_not: { - exists: { - field: 'event.ingested', - }, - }, - }, - }, - ], - }, - }, - ], - }, - }, - emptyFilter, - ], - }, - }, - fields: [ - { - field: '*', - include_unmapped: true, - }, - { - field: 'event.ingested', - format: 'strict_date_optional_time', - }, - { - field: '@timestamp', - format: 'strict_date_optional_time', - }, - ], - }, - }); - }); - - test('should build a request without @timestamp fallback if secondaryTimestamp is not specified', () => { - const request = buildEqlSearchRequest({ - query: 'process where true', - index: ['testindex1', 'testindex2'], - from: 'now-5m', - to: 'now', - size: 100, - filters: undefined, - primaryTimestamp: 'event.ingested', - secondaryTimestamp: undefined, - runtimeMappings: undefined, - eventCategoryOverride: 'event.other_category', - timestampField: undefined, - exceptionFilter: undefined, - }); - expect(request).toEqual({ - allow_no_indices: true, - index: ['testindex1', 'testindex2'], - body: { - event_category_field: 'event.other_category', - size: 100, - query: 'process where true', - runtime_mappings: undefined, - filter: { - bool: { - filter: [ - { - range: { - 'event.ingested': { - lte: 'now', - gte: 'now-5m', - format: 'strict_date_optional_time', - }, - }, - }, - emptyFilter, - ], - }, - }, - fields: [ - { - field: '*', - include_unmapped: true, - }, - { - field: 'event.ingested', - format: 'strict_date_optional_time', - }, - ], - }, - }); - }); - - test('should build a request with exceptions', async () => { - const { filter } = await buildExceptionFilter({ - listClient: getListClientMock(), - lists: [getExceptionListItemSchemaMock()], - alias: null, - chunkSize: 1024, - excludeExceptions: true, - startedAt: new Date(), - }); - const request = buildEqlSearchRequest({ - query: 'process where true', - index: ['testindex1', 'testindex2'], - from: 'now-5m', - to: 'now', - size: 100, - filters: undefined, - primaryTimestamp: '@timestamp', - secondaryTimestamp: undefined, - runtimeMappings: undefined, - eventCategoryOverride: undefined, - exceptionFilter: filter, - }); - expect(request).toMatchInlineSnapshot(` - Object { - "allow_no_indices": true, - "body": Object { - "event_category_field": undefined, - "fields": Array [ - Object { - "field": "*", - "include_unmapped": true, - }, - Object { - "field": "@timestamp", - "format": "strict_date_optional_time", - }, - ], - "filter": Object { - "bool": Object { - "filter": Array [ - Object { - "range": Object { - "@timestamp": Object { - "format": "strict_date_optional_time", - "gte": "now-5m", - "lte": "now", - }, - }, - }, - Object { - "bool": Object { - "filter": Array [], - "must": Array [], - "must_not": Array [ - Object { - "bool": Object { - "should": Array [ - Object { - "bool": Object { - "filter": Array [ - Object { - "nested": Object { - "path": "some.parentField", - "query": Object { - "bool": Object { - "minimum_should_match": 1, - "should": Array [ - Object { - "match_phrase": Object { - "some.parentField.nested.field": "some value", - }, - }, - ], - }, - }, - "score_mode": "none", - }, - }, - Object { - "bool": Object { - "minimum_should_match": 1, - "should": Array [ - Object { - "match_phrase": Object { - "some.not.nested.field": "some value", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - "should": Array [], - }, - }, - ], - }, - }, - "query": "process where true", - "runtime_mappings": undefined, - "size": 100, - "tiebreaker_field": undefined, - "timestamp_field": undefined, - }, - "index": Array [ - "testindex1", - "testindex2", - ], - } - `); - }); - - test('should build a request with filters', () => { - const filters = [ - { - meta: { - alias: null, - negate: false, - disabled: false, - type: 'exists', - key: 'process.name', - value: 'exists', - }, - query: { - exists: { - field: 'process.name', - }, - }, - }, - { - meta: { - alias: null, - negate: false, - disabled: false, - type: 'phrase', - key: 'host.name', - params: { - query: 'Host-b4d9hu1a56', - }, - }, - query: { - match_phrase: { - 'host.name': 'Host-b4d9hu1a56', - }, - }, - }, - ]; - const request = buildEqlSearchRequest({ - query: 'process where true', - index: ['testindex1', 'testindex2'], - from: 'now-5m', - to: 'now', - size: 100, - filters, - primaryTimestamp: '@timestamp', - secondaryTimestamp: undefined, - runtimeMappings: undefined, - exceptionFilter: undefined, - }); - expect(request).toEqual({ - allow_no_indices: true, - index: ['testindex1', 'testindex2'], - body: { - size: 100, - query: 'process where true', - filter: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: 'now-5m', - lte: 'now', - format: 'strict_date_optional_time', - }, - }, - }, - { - bool: { - must: [], - filter: [ - { - exists: { - field: 'process.name', - }, - }, - { - match_phrase: { - 'host.name': 'Host-b4d9hu1a56', - }, - }, - ], - should: [], - must_not: [], - }, - }, - ], - }, - }, - fields: [ - { - field: '*', - include_unmapped: true, - }, - { - field: '@timestamp', - format: 'strict_date_optional_time', - }, - ], - }, - }); - }); - }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/build_events_query.ts similarity index 71% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/build_events_query.ts index a04e27c1f8837..3f0cac4d7089b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/build_events_query.ts @@ -6,13 +6,8 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isEmpty } from 'lodash'; -import type { Filter } from '@kbn/es-query'; -import type { OverrideBodyQuery } from './types'; -import type { - RuleFilterArray, - TimestampOverride, -} from '../../../../common/detection_engine/rule_schema'; -import { getQueryFilter } from './get_query_filter'; +import type { OverrideBodyQuery } from '../types'; +import type { TimestampOverride } from '../../../../../common/detection_engine/rule_schema'; interface BuildEventsSearchQuery { aggregations?: Record; @@ -31,22 +26,6 @@ interface BuildEventsSearchQuery { overrideBody?: OverrideBodyQuery; } -interface BuildEqlSearchRequestParams { - query: string; - index: string[]; - from: string; - to: string; - size: number; - filters: RuleFilterArray | undefined; - primaryTimestamp: TimestampOverride; - secondaryTimestamp: TimestampOverride | undefined; - runtimeMappings: estypes.MappingRuntimeFields | undefined; - eventCategoryOverride?: string; - timestampField?: string; - tiebreakerField?: string; - exceptionFilter: Filter | undefined; -} - export const buildTimeRangeFilter = ({ to, from, @@ -211,68 +190,3 @@ export const buildEventsSearchQuery = ({ } return searchQuery; }; - -export const buildEqlSearchRequest = ({ - query, - index, - from, - to, - size, - filters, - primaryTimestamp, - secondaryTimestamp, - runtimeMappings, - eventCategoryOverride, - timestampField, - tiebreakerField, - exceptionFilter, -}: BuildEqlSearchRequestParams): estypes.EqlSearchRequest => { - const timestamps = secondaryTimestamp - ? [primaryTimestamp, secondaryTimestamp] - : [primaryTimestamp]; - const docFields = timestamps.map((tstamp) => ({ - field: tstamp, - format: 'strict_date_optional_time', - })); - - const esFilter = getQueryFilter({ - query: '', - language: 'eql', - filters: filters || [], - index, - exceptionFilter, - }); - - const rangeFilter = buildTimeRangeFilter({ - to, - from, - primaryTimestamp, - secondaryTimestamp, - }); - const requestFilter: estypes.QueryDslQueryContainer[] = [rangeFilter, esFilter]; - const fields = [ - { - field: '*', - include_unmapped: true, - }, - ...docFields, - ]; - return { - index, - allow_no_indices: true, - body: { - size, - query, - filter: { - bool: { - filter: requestFilter, - }, - }, - runtime_mappings: runtimeMappings, - timestamp_field: timestampField, - event_category_field: eventCategoryOverride, - tiebreaker_field: tiebreakerField, - fields, - }, - }; -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/__mocks__/alerts.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/__mocks__/alerts.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts index f837553b8b062..43cd37aca396a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/__mocks__/alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/__mocks__/alerts.ts @@ -46,7 +46,7 @@ import { } from '@kbn/rule-data-utils'; import type { EventsForEnrichment } from '../types'; -import type { BaseFieldsLatest } from '../../../../../../common/detection_engine/schemas/alerts'; +import type { BaseFieldsLatest } from '../../../../../../../common/detection_engine/schemas/alerts'; import { ALERT_ANCESTORS, @@ -65,7 +65,7 @@ import { ALERT_RULE_TIMELINE_TITLE, ALERT_RULE_INDICES, ALERT_RULE_TIMESTAMP_OVERRIDE, -} from '../../../../../../common/field_maps/field_names'; +} from '../../../../../../../common/field_maps/field_names'; export const createAlert = ( someUuid: string = '1', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/create_single_field_match_enrichment.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/create_single_field_match_enrichment.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/create_single_field_match_enrichment.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/create_single_field_match_enrichment.test.ts index d7e29d51a0025..8134bb9380660 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/create_single_field_match_enrichment.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/create_single_field_match_enrichment.test.ts @@ -9,7 +9,7 @@ import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { createSingleFieldMatchEnrichment } from './create_single_field_match_enrichment'; import { searchEnrichments } from './search_enrichments'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; import { createAlert } from './__mocks__/alerts'; import type { EnrichmentFunction } from './types'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/create_single_field_match_enrichment.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/create_single_field_match_enrichment.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/create_single_field_match_enrichment.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/create_single_field_match_enrichment.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/enrichment_by_type/host_risk.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/host_risk.ts similarity index 89% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/enrichment_by_type/host_risk.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/host_risk.ts index fb061d06ce1e2..4d5ef11788aea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/enrichment_by_type/host_risk.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/host_risk.ts @@ -7,8 +7,8 @@ import { set } from '@kbn/safer-lodash-set'; import { cloneDeep } from 'lodash'; -import { getHostRiskIndex } from '../../../../../../common/search_strategy/security_solution/risk_score/common'; -import { RiskScoreFields } from '../../../../../../common/search_strategy/security_solution/risk_score/all'; +import { getHostRiskIndex } from '../../../../../../../common/search_strategy/security_solution/risk_score/common'; +import { RiskScoreFields } from '../../../../../../../common/search_strategy/security_solution/risk_score/all'; import { createSingleFieldMatchEnrichment } from '../create_single_field_match_enrichment'; import type { CreateRiskEnrichment, GetIsRiskScoreAvailable } from '../types'; import { getFieldValue } from '../utils/events'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/enrichment_by_type/user_risk.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/user_risk.ts similarity index 89% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/enrichment_by_type/user_risk.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/user_risk.ts index db959a7671546..e80b61dfa5267 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/enrichment_by_type/user_risk.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/enrichment_by_type/user_risk.ts @@ -6,8 +6,8 @@ */ import { set } from '@kbn/safer-lodash-set'; import { cloneDeep } from 'lodash'; -import { getUserRiskIndex } from '../../../../../../common/search_strategy/security_solution/risk_score/common'; -import { RiskScoreFields } from '../../../../../../common/search_strategy/security_solution/risk_score/all'; +import { getUserRiskIndex } from '../../../../../../../common/search_strategy/security_solution/risk_score/common'; +import { RiskScoreFields } from '../../../../../../../common/search_strategy/security_solution/risk_score/all'; import { createSingleFieldMatchEnrichment } from '../create_single_field_match_enrichment'; import type { CreateRiskEnrichment, GetIsRiskScoreAvailable } from '../types'; import { getFieldValue } from '../utils/events'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/index.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/index.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts index 4ea17dfbc0092..8f98b5bfe04b7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.test.ts @@ -9,7 +9,7 @@ import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { enrichEvents } from '.'; import { searchEnrichments } from './search_enrichments'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; import { createAlert } from './__mocks__/alerts'; import { getIsHostRiskScoreAvailable } from './enrichment_by_type/host_risk'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/search_enrichments.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/search_enrichments.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/search_enrichments.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/search_enrichments.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/types.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/types.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/types.ts index 244311fe67df5..1fe7fa9ecfb20 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/types.ts @@ -11,9 +11,9 @@ import type { Filter } from '@kbn/es-query'; import type { BaseFieldsLatest, WrappedFieldsLatest, -} from '../../../../../common/detection_engine/schemas/alerts'; -import type { RuleServices } from '../types'; -import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +} from '../../../../../../common/detection_engine/schemas/alerts'; +import type { RuleServices } from '../../types'; +import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; export type EnrichmentType = estypes.SearchHit; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/events.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/events.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/events.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/events.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/events.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/events.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/events.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/events.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/requests.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/requests.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/requests.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/requests.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/requests.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/requests.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/requests.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/requests.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/transforms.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/transforms.test.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/transforms.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/transforms.test.ts index 0e6de54014c3c..c9eb3a5fea40a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/transforms.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/transforms.test.ts @@ -6,7 +6,7 @@ */ import { applyEnrichmentsToEvents, mergeEnrichments } from './transforms'; -import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../../rule_monitoring/mocks'; import { createAlert } from '../__mocks__/alerts'; import type { EnrichmentFunction } from '../types'; import { set } from '@kbn/safer-lodash-set'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/transforms.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/transforms.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/enrichments/utils/transforms.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/enrichments/utils/transforms.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts similarity index 88% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts index 33d710ed2ffa4..cd1f2d5227a7e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts @@ -17,12 +17,15 @@ import type { RuleExecutorServices, } from '@kbn/alerting-plugin/server'; import type { Filter } from '@kbn/es-query'; -import { assertUnreachable } from '../../../../common/utility_types'; -import type { IndexPatternArray, RuleQuery } from '../../../../common/detection_engine/rule_schema'; -import type { SavedIdOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas'; -import type { PartialFilter } from '../types'; -import { withSecuritySpan } from '../../../utils/with_security_span'; -import type { ESBoolQuery } from '../../../../common/typed_json'; +import { assertUnreachable } from '../../../../../common/utility_types'; +import type { + IndexPatternArray, + RuleQuery, +} from '../../../../../common/detection_engine/rule_schema'; +import type { SavedIdOrUndefined } from '../../../../../common/detection_engine/schemas/common/schemas'; +import type { PartialFilter } from '../../types'; +import { withSecuritySpan } from '../../../../utils/with_security_span'; +import type { ESBoolQuery } from '../../../../../common/typed_json'; import { getQueryFilter } from './get_query_filter'; interface GetFilterArgs { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_input_output_index.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_input_output_index.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_input_output_index.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_input_output_index.test.ts index c898dff30c867..2b024a6932968 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_input_output_index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_input_output_index.test.ts @@ -10,7 +10,7 @@ import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import type { MockedLogger } from '@kbn/logging-mocks'; import { loggerMock } from '@kbn/logging-mocks'; -import { DEFAULT_INDEX_KEY, DEFAULT_INDEX_PATTERN } from '../../../../common/constants'; +import { DEFAULT_INDEX_KEY, DEFAULT_INDEX_PATTERN } from '../../../../../common/constants'; import type { GetInputIndex } from './get_input_output_index'; import { getInputIndex, DataViewError } from './get_input_output_index'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_input_output_index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_input_output_index.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_input_output_index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_input_output_index.ts index b75c351c84f5f..4ec860bc5ae65 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_input_output_index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_input_output_index.ts @@ -14,8 +14,8 @@ import type { DataViewAttributes } from '@kbn/data-views-plugin/common'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { Logger } from '@kbn/core/server'; -import { DEFAULT_INDEX_KEY, DEFAULT_INDEX_PATTERN } from '../../../../common/constants'; -import { withSecuritySpan } from '../../../utils/with_security_span'; +import { DEFAULT_INDEX_KEY, DEFAULT_INDEX_PATTERN } from '../../../../../common/constants'; +import { withSecuritySpan } from '../../../../utils/with_security_span'; export interface GetInputIndex { index: string[] | null | undefined; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts similarity index 88% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts index 15477388839e4..aa6062d321b3a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts @@ -8,8 +8,11 @@ import type { Language } from '@kbn/securitysolution-io-ts-alerting-types'; import type { Filter, EsQueryConfig, DataViewBase } from '@kbn/es-query'; import { buildEsQuery } from '@kbn/es-query'; -import type { ESBoolQuery } from '../../../../common/typed_json'; -import type { IndexPatternArray, RuleQuery } from '../../../../common/detection_engine/rule_schema'; +import type { ESBoolQuery } from '../../../../../common/typed_json'; +import type { + IndexPatternArray, + RuleQuery, +} from '../../../../../common/detection_engine/rule_schema'; export const getQueryFilter = ({ query, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_field_and_set_tuples.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_field_and_set_tuples.test.ts index d6b452216be92..593a5fef0bf79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_field_and_set_tuples.test.ts @@ -6,13 +6,13 @@ */ import { createFieldAndSetTuples } from './create_field_and_set_tuples'; -import { sampleDocWithSortId } from '../__mocks__/es_results'; +import { sampleDocWithSortId } from '../../__mocks__/es_results'; import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; import { listMock } from '@kbn/lists-plugin/server/mocks'; import { getSearchListItemResponseMock } from '@kbn/lists-plugin/common/schemas/response/search_list_item_schema.mock'; import type { EntryList } from '@kbn/securitysolution-io-ts-list-types'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; describe('filterEventsAgainstList', () => { let listClient = listMock.getListClient(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_field_and_set_tuples.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_field_and_set_tuples.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_set_to_filter_against.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_set_to_filter_against.test.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_set_to_filter_against.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_set_to_filter_against.test.ts index d28bc2a39418d..eff2f6f0cd265 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_set_to_filter_against.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_set_to_filter_against.test.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { sampleDocWithSortId } from '../__mocks__/es_results'; +import { sampleDocWithSortId } from '../../__mocks__/es_results'; import { listMock } from '@kbn/lists-plugin/server/mocks'; import { getSearchListItemResponseMock } from '@kbn/lists-plugin/common/schemas/response/search_list_item_schema.mock'; import { createSetToFilterAgainst } from './create_set_to_filter_against'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; describe('createSetToFilterAgainst', () => { let listClient = listMock.getListClient(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_set_to_filter_against.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_set_to_filter_against.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_set_to_filter_against.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/create_set_to_filter_against.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events.test.ts index 94fa5f01358be..0f2bd7280642c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { sampleDocWithSortId } from '../__mocks__/es_results'; +import { sampleDocWithSortId } from '../../__mocks__/es_results'; import { listMock } from '@kbn/lists-plugin/server/mocks'; import { getSearchListItemResponseMock } from '@kbn/lists-plugin/common/schemas/response/search_list_item_schema.mock'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events_against_list.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events_against_list.test.ts index c7c1824d76c69..a50b33a0eee34 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events_against_list.test.ts @@ -12,8 +12,8 @@ import { getSearchListItemResponseMock } from '@kbn/lists-plugin/common/schemas/ import { listMock } from '@kbn/lists-plugin/server/mocks'; import { filterEventsAgainstList } from './filter_events_against_list'; -import { repeatedHitsWithSortId } from '../__mocks__/es_results'; -import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import { repeatedHitsWithSortId } from '../../__mocks__/es_results'; +import { ruleExecutionLogMock } from '../../../rule_monitoring/mocks'; const someGuids = Array.from({ length: 13 }).map((x) => uuidv4()); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events_against_list.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/filter_events_against_list.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/types.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/types.ts index f4f8aaf91f969..859000e538fa4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/large_list_filters/types.ts @@ -7,7 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { Type, ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import type { ListClient } from '@kbn/lists-plugin/server'; -import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +import type { IRuleExecutionLogForExecutors } from '../../../rule_monitoring'; export interface FilterEventsAgainstListOptions { listClient: ListClient; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_risk_score_from_mapping.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_risk_score_from_mapping.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_risk_score_from_mapping.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_risk_score_from_mapping.test.ts index 5ae4aff3a6687..c144bac9f1181 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_risk_score_from_mapping.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_risk_score_from_mapping.test.ts @@ -6,7 +6,7 @@ */ import type { RiskScore, RiskScoreMapping } from '@kbn/securitysolution-io-ts-alerting-types'; -import { sampleDocRiskScore } from '../__mocks__/es_results'; +import { sampleDocRiskScore } from '../../__mocks__/es_results'; import type { BuildRiskScoreFromMappingReturn } from './build_risk_score_from_mapping'; import { buildRiskScoreFromMapping } from './build_risk_score_from_mapping'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_risk_score_from_mapping.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_risk_score_from_mapping.ts similarity index 95% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_risk_score_from_mapping.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_risk_score_from_mapping.ts index e17c5b941cbb5..95a7034b5310b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_risk_score_from_mapping.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_risk_score_from_mapping.ts @@ -8,8 +8,8 @@ import { get } from 'lodash/fp'; import type { RiskScore, RiskScoreMapping } from '@kbn/securitysolution-io-ts-alerting-types'; -import type { RuleMetadata } from '../../../../../common/detection_engine/rule_schema'; -import type { SignalSource } from '../types'; +import type { RuleMetadata } from '../../../../../../common/detection_engine/rule_schema'; +import type { SignalSource } from '../../types'; export interface BuildRiskScoreFromMappingProps { eventSource: SignalSource; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_rule_name_from_mapping.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_rule_name_from_mapping.test.ts similarity index 92% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_rule_name_from_mapping.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_rule_name_from_mapping.test.ts index 23e5aecc5c553..40bd694ce7d52 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_rule_name_from_mapping.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_rule_name_from_mapping.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { sampleDocNoSortId } from '../__mocks__/es_results'; +import { sampleDocNoSortId } from '../../__mocks__/es_results'; import { buildRuleNameFromMapping } from './build_rule_name_from_mapping'; describe('buildRuleNameFromMapping', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_rule_name_from_mapping.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_rule_name_from_mapping.ts similarity index 90% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_rule_name_from_mapping.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_rule_name_from_mapping.ts index 933a330a77098..7bc9c987a4d10 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_rule_name_from_mapping.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_rule_name_from_mapping.ts @@ -12,8 +12,8 @@ import type { RuleMetadata, RuleName, RuleNameOverride, -} from '../../../../../common/detection_engine/rule_schema'; -import type { SignalSource } from '../types'; +} from '../../../../../../common/detection_engine/rule_schema'; +import type { SignalSource } from '../../types'; interface BuildRuleNameFromMappingProps { eventSource: SignalSource; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_severity_from_mapping.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_severity_from_mapping.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_severity_from_mapping.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_severity_from_mapping.test.ts index 875da0124b42f..99a82ed03fb9f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_severity_from_mapping.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_severity_from_mapping.test.ts @@ -6,7 +6,7 @@ */ import type { Severity, SeverityMapping } from '@kbn/securitysolution-io-ts-alerting-types'; -import { sampleDocSeverity } from '../__mocks__/es_results'; +import { sampleDocSeverity } from '../../__mocks__/es_results'; import type { BuildSeverityFromMappingReturn } from './build_severity_from_mapping'; import { buildSeverityFromMapping } from './build_severity_from_mapping'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_severity_from_mapping.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_severity_from_mapping.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_severity_from_mapping.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_severity_from_mapping.ts index 53691eeb98814..2a25d00e85f22 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/mappings/build_severity_from_mapping.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/mappings/build_severity_from_mapping.ts @@ -13,9 +13,9 @@ import type { SeverityMappingItem, } from '@kbn/securitysolution-io-ts-alerting-types'; -import type { RuleMetadata } from '../../../../../common/detection_engine/rule_schema'; -import type { SearchTypes } from '../../../../../common/detection_engine/types'; -import type { SignalSource } from '../types'; +import type { RuleMetadata } from '../../../../../../common/detection_engine/rule_schema'; +import type { SearchTypes } from '../../../../../../common/detection_engine/types'; +import type { SignalSource } from '../../types'; export interface BuildSeverityFromMappingProps { eventSource: SignalSource; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/reason_formatter.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/reason_formatter.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/reason_formatter.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/reason_formatter.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/reason_formatters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/reason_formatters.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/reason_formatters.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/reason_formatters.ts index 28dbc5cc0912b..806edf3765873 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/reason_formatters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/reason_formatters.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { getOr } from 'lodash/fp'; -import type { SignalSourceHit } from './types'; +import type { SignalSourceHit } from '../types'; export interface BuildReasonMessageArgs { name: string; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts index caaf0b8c4cf73..5cdc73d4015b4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.test.ts @@ -11,26 +11,21 @@ import { repeatedSearchResultsWithNoSortId, sampleDocSearchResultsNoSortIdNoHits, sampleDocWithSortId, -} from './__mocks__/es_results'; +} from '../__mocks__/es_results'; import { searchAfterAndBulkCreate } from './search_after_bulk_create'; import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks'; import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { v4 as uuidv4 } from 'uuid'; import { listMock } from '@kbn/lists-plugin/server/mocks'; import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; -import type { BulkCreate, BulkResponse, RuleRangeTuple, WrapHits } from './types'; import type { SearchListItemArraySchema } from '@kbn/securitysolution-io-ts-list-types'; import { getSearchListItemResponseMock } from '@kbn/lists-plugin/common/schemas/response/search_list_item_schema.mock'; -import { getRuleRangeTuples } from './utils'; + import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; -import { getCompleteRuleMock, getQueryRuleParams } from '../rule_schema/mocks'; -import { bulkCreateFactory } from '../rule_types/factories/bulk_create_factory'; -import { wrapHitsFactory } from '../rule_types/factories/wrap_hits_factory'; -import { ruleExecutionLogMock } from '../rule_monitoring/mocks'; -import type { BuildReasonMessage } from './reason_formatters'; -import type { QueryRuleParams } from '../rule_schema'; + import { createPersistenceServicesMock } from '@kbn/rule-registry-plugin/server/utils/create_persistence_rule_type_wrapper.mock'; import type { PersistenceServices } from '@kbn/rule-registry-plugin/server'; +import type { CommonAlertFieldsLatest } from '@kbn/rule-registry-plugin/common/schemas'; import { ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, @@ -44,8 +39,15 @@ import { SPACE_IDS, TIMESTAMP, } from '@kbn/rule-data-utils'; -import { SERVER_APP_ID } from '../../../../common/constants'; -import type { CommonAlertFieldsLatest } from '@kbn/rule-registry-plugin/common/schemas'; +import type { BulkCreate, BulkResponse, RuleRangeTuple, WrapHits } from '../types'; +import { getRuleRangeTuples } from './utils'; +import { getCompleteRuleMock, getQueryRuleParams } from '../../rule_schema/mocks'; +import { bulkCreateFactory } from '../factories/bulk_create_factory'; +import { wrapHitsFactory } from '../factories/wrap_hits_factory'; +import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import type { BuildReasonMessage } from './reason_formatters'; +import type { QueryRuleParams } from '../../rule_schema'; +import { SERVER_APP_ID } from '../../../../../common/constants'; describe('searchAfterAndBulkCreate', () => { let mockService: RuleExecutorServicesMock; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.ts similarity index 97% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.ts index e57e6603cb067..78bead8d70ff6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create.ts @@ -8,7 +8,7 @@ import { identity } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { singleSearchAfter } from './single_search_after'; -import { filterEventsAgainstList } from './filters/filter_events_against_list'; +import { filterEventsAgainstList } from './large_list_filters/filter_events_against_list'; import { sendAlertTelemetryEvents } from './send_telemetry_events'; import { createSearchAfterReturnType, @@ -20,8 +20,8 @@ import { getSafeSortIds, addToSearchAfterReturn, } from './utils'; -import type { SearchAfterAndBulkCreateParams, SearchAfterAndBulkCreateReturnType } from './types'; -import { withSecuritySpan } from '../../../utils/with_security_span'; +import type { SearchAfterAndBulkCreateParams, SearchAfterAndBulkCreateReturnType } from '../types'; +import { withSecuritySpan } from '../../../../utils/with_security_span'; import { createEnrichEventsFunction } from './enrichments'; // search_after through documents and re-index using bulk endpoint. diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/send_telemetry_events.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/send_telemetry_events.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/send_telemetry_events.ts similarity index 89% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/send_telemetry_events.ts index 65742d5145110..a4687fa953dfe 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/send_telemetry_events.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/send_telemetry_events.ts @@ -5,10 +5,10 @@ * 2.0. */ -import type { ITelemetryEventsSender } from '../../telemetry/sender'; -import type { TelemetryEvent } from '../../telemetry/types'; -import type { IRuleExecutionLogForExecutors } from '../rule_monitoring'; -import type { SignalSource, SignalSourceHit } from './types'; +import type { ITelemetryEventsSender } from '../../../telemetry/sender'; +import type { TelemetryEvent } from '../../../telemetry/types'; +import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +import type { SignalSource, SignalSourceHit } from '../types'; interface SearchResultSource { _source: SignalSource; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/siem_rule_action_groups.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/siem_rule_action_groups.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/siem_rule_action_groups.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/siem_rule_action_groups.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/single_search_after.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/single_search_after.test.ts index 7b4e1b8ecf00a..136951ebb0b4a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/single_search_after.test.ts @@ -8,12 +8,12 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { sampleDocSearchResultsNoSortId, sampleDocSearchResultsWithSortId, -} from './__mocks__/es_results'; +} from '../__mocks__/es_results'; import { singleSearchAfter } from './single_search_after'; import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks'; import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; -import { ruleExecutionLogMock } from '../rule_monitoring/mocks'; +import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; import { buildEventsSearchQuery } from './build_events_query'; jest.mock('./build_events_query'); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/single_search_after.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/single_search_after.ts index 3be6f3ad30e49..eea89c880e04f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/single_search_after.ts @@ -11,12 +11,12 @@ import type { AlertInstanceState, RuleExecutorServices, } from '@kbn/alerting-plugin/server'; -import type { SignalSearchResponse, SignalSource, OverrideBodyQuery } from './types'; +import type { SignalSearchResponse, SignalSource, OverrideBodyQuery } from '../types'; import { buildEventsSearchQuery } from './build_events_query'; import { createErrorsFromShard, makeFloatString } from './utils'; -import type { TimestampOverride } from '../../../../common/detection_engine/rule_schema'; -import { withSecuritySpan } from '../../../utils/with_security_span'; -import type { IRuleExecutionLogForExecutors } from '../rule_monitoring'; +import type { TimestampOverride } from '../../../../../common/detection_engine/rule_schema'; +import { withSecuritySpan } from '../../../../utils/with_security_span'; +import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; interface SingleSearchAfterParams { aggregations?: Record; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/README.md b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/README.md similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/README.md rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/README.md diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/get_strategy.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/get_strategy.ts similarity index 86% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/get_strategy.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/get_strategy.ts index 636a0bbb3de6f..ab339fdd6f68f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/get_strategy.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/get_strategy.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { assertUnreachable } from '../../../../../../common/utility_types'; -import type { ConfigType } from '../../../../../config'; +import { assertUnreachable } from '../../../../../../../common/utility_types'; +import type { ConfigType } from '../../../../../../config'; import type { MergeStrategyFunction } from '../types'; import { mergeAllFieldsWithSource } from './merge_all_fields_with_source'; import { mergeMissingFieldsWithSource } from './merge_missing_fields_with_source'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_all_fields_with_source.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_all_fields_with_source.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts index 74445d4be790a..5aac1418cf45d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_all_fields_with_source.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts @@ -6,8 +6,8 @@ */ import { mergeAllFieldsWithSource } from './merge_all_fields_with_source'; -import type { SignalSourceHit } from '../../types'; -import { emptyEsResult } from '../../__mocks__/empty_signal_source_hit'; +import type { SignalSourceHit } from '../../../types'; +import { emptyEsResult } from '../../../__mocks__/empty_signal_source_hit'; /** * See ../README.md for the nomenclature of any notes within tests below diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_all_fields_with_source.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_all_fields_with_source.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts index e3c7f8f5ee50e..b9193f952fd18 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_all_fields_with_source.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts @@ -7,7 +7,7 @@ import { get } from 'lodash/fp'; import { set } from '@kbn/safer-lodash-set/fp'; -import type { SignalSource } from '../../types'; +import type { SignalSource } from '../../../types'; import { filterFieldEntries } from '../utils/filter_field_entries'; import type { FieldsType, MergeStrategyFunction } from '../types'; import { isObjectLikeOrArrayOfObjectLikes } from '../utils/is_objectlike_or_array_of_objectlikes'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts index f5863533ea283..911df7400ec63 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts @@ -6,8 +6,8 @@ */ import { performance } from 'perf_hooks'; import { mergeMissingFieldsWithSource } from './merge_missing_fields_with_source'; -import type { SignalSourceHit } from '../../types'; -import { emptyEsResult } from '../../__mocks__/empty_signal_source_hit'; +import type { SignalSourceHit } from '../../../types'; +import { emptyEsResult } from '../../../__mocks__/empty_signal_source_hit'; /** * See ../README.md for the nomenclature of any notes within tests below diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts index c20f6b55301bd..3efe1a7925d9b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts @@ -7,7 +7,7 @@ import { get } from 'lodash/fp'; import { set } from '@kbn/safer-lodash-set'; -import type { SignalSource } from '../../types'; +import type { SignalSource } from '../../../types'; import { filterFieldEntries } from '../utils/filter_field_entries'; import type { FieldsType, MergeStrategyFunction } from '../types'; import { recursiveUnboxingFields } from '../utils/recursive_unboxing_fields'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_no_fields.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_no_fields.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_no_fields.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_no_fields.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/types.ts similarity index 93% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/types.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/types.ts index 56ca8fb460374..68d0c2f047727 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SignalSourceHit } from '../types'; +import type { SignalSourceHit } from '../../types'; /** * A bit stricter typing since the default fields type is an "any" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/array_in_path_exists.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/array_in_path_exists.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/array_in_path_exists.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/array_in_path_exists.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/array_in_path_exists.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/array_in_path_exists.ts similarity index 94% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/array_in_path_exists.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/array_in_path_exists.ts index cc891b0f609a1..e13dd0ffdd5f1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/array_in_path_exists.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/array_in_path_exists.ts @@ -6,7 +6,7 @@ */ import { get } from 'lodash/fp'; -import type { SignalSource } from '../../types'; +import type { SignalSource } from '../../../types'; /** * Returns true if an array within the path exists anywhere. diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/filter_field_entries.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/filter_field_entries.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/filter_field_entries.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/filter_field_entries.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/filter_field_entries.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/filter_field_entries.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/filter_field_entries.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/filter_field_entries.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/index.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_array_of_primitives.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_array_of_primitives.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_array_of_primitives.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_array_of_primitives.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_array_of_primitives.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_array_of_primitives.ts similarity index 90% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_array_of_primitives.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_array_of_primitives.ts index 80916659b8a12..765eb66354dd2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_array_of_primitives.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_array_of_primitives.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SearchTypes } from '../../../../../../common/detection_engine/types'; +import type { SearchTypes } from '../../../../../../../common/detection_engine/types'; import { isPrimitive } from './is_primitive'; /** diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_eql_bug_77152.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_eql_bug_77152.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_eql_bug_77152.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_eql_bug_77152.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_eql_bug_77152.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_eql_bug_77152.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_eql_bug_77152.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_eql_bug_77152.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_ignored.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_ignored.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_ignored.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_ignored.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_ignored.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_ignored.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_ignored.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_ignored.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_invalid_key.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_invalid_key.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_invalid_key.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_invalid_key.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_invalid_key.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_invalid_key.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_invalid_key.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_invalid_key.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_multifield.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_multifield.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_multifield.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_multifield.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_multifield.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_multifield.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_multifield.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_multifield.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_nested_object.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_nested_object.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_nested_object.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_nested_object.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_nested_object.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_nested_object.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_nested_object.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_nested_object.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.ts similarity index 91% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.ts index 38c3db1d8fd24..39d215d4c5062 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_objectlike_or_array_of_objectlikes.ts @@ -6,7 +6,7 @@ */ import { isObjectLike } from 'lodash/fp'; -import type { SearchTypes } from '../../../../../../common/detection_engine/types'; +import type { SearchTypes } from '../../../../../../../common/detection_engine/types'; /** * Returns true if at least one element is an object, otherwise false if they all are not objects diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_primitive.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_primitive.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_primitive.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_primitive.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_primitive.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_primitive.ts similarity index 85% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_primitive.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_primitive.ts index fd9997ba66a55..bd053036176cc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_primitive.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_primitive.ts @@ -6,7 +6,7 @@ */ import { isObjectLike } from 'lodash/fp'; -import type { SearchTypes } from '../../../../../../common/detection_engine/types'; +import type { SearchTypes } from '../../../../../../../common/detection_engine/types'; /** * Returns true if it is a primitive type, otherwise false diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_type_object.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_type_object.test.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_type_object.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_type_object.test.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_type_object.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_type_object.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/is_type_object.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_type_object.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/recursive_unboxing_fields.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/recursive_unboxing_fields.test.ts similarity index 99% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/recursive_unboxing_fields.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/recursive_unboxing_fields.test.ts index 2d2febf9901d3..c606c87812c16 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/recursive_unboxing_fields.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/recursive_unboxing_fields.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SearchTypes } from '../../../../../../common/detection_engine/types'; +import type { SearchTypes } from '../../../../../../../common/detection_engine/types'; import { recursiveUnboxingFields } from './recursive_unboxing_fields'; import type { FieldsType } from '../types'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/recursive_unboxing_fields.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/recursive_unboxing_fields.ts similarity index 96% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/recursive_unboxing_fields.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/recursive_unboxing_fields.ts index 8bb490c2d62df..55f7e30c256a3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/utils/recursive_unboxing_fields.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/recursive_unboxing_fields.ts @@ -7,7 +7,7 @@ import { get } from 'lodash/fp'; import { set } from '@kbn/safer-lodash-set/fp'; -import type { SearchTypes } from '../../../../../../common/detection_engine/types'; +import type { SearchTypes } from '../../../../../../../common/detection_engine/types'; import type { FieldsType } from '../types'; /** diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts index d80ed256a0de0..e39573562d277 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts @@ -14,8 +14,8 @@ import type { RuleExecutorServicesMock } from '@kbn/alerting-plugin/server/mocks import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { listMock } from '@kbn/lists-plugin/server/mocks'; import type { ExceptionListClient } from '@kbn/lists-plugin/server'; -import { RuleExecutionStatus } from '../../../../common/detection_engine/rule_monitoring'; -import { getListArrayMock } from '../../../../common/detection_engine/schemas/types/lists.mock'; +import { RuleExecutionStatus } from '../../../../../common/detection_engine/rule_monitoring'; +import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; moment.suppressDeprecationWarnings = true; @@ -37,7 +37,6 @@ import { createSearchAfterReturnType, mergeReturns, lastValidDate, - calculateThresholdSignalUuid, buildChunkedOrFilter, getValidDateFromDoc, calculateTotal, @@ -47,7 +46,7 @@ import { addToSearchAfterReturn, getUnprocessedExceptionsWarnings, } from './utils'; -import type { BulkResponseErrorAggregation, SearchAfterAndBulkCreateReturnType } from './types'; +import type { BulkResponseErrorAggregation, SearchAfterAndBulkCreateReturnType } from '../types'; import { sampleBulkResponse, sampleEmptyBulkResponse, @@ -61,11 +60,11 @@ import { sampleDocNoSortId, sampleAlertDocNoSortIdWithTimestamp, sampleAlertDocAADNoSortIdWithTimestamp, -} from './__mocks__/es_results'; -import type { ShardError } from '../../types'; -import { ruleExecutionLogMock } from '../rule_monitoring/mocks'; -import type { GenericBulkCreateResponse } from '../rule_types/factories'; -import type { BaseFieldsLatest } from '../../../../common/detection_engine/schemas/alerts'; +} from '../__mocks__/es_results'; +import type { ShardError } from '../../../types'; +import { ruleExecutionLogMock } from '../../rule_monitoring/mocks'; +import type { GenericBulkCreateResponse } from '../factories'; +import type { BaseFieldsLatest } from '../../../../../common/detection_engine/schemas/alerts'; describe('utils', () => { const anchor = '2020-01-01T06:06:06.666Z'; @@ -1508,20 +1507,6 @@ describe('utils', () => { }); }); - describe('calculateThresholdSignalUuid', () => { - it('should generate a uuid without key', () => { - const startedAt = new Date('2020-12-17T16:27:00Z'); - const signalUuid = calculateThresholdSignalUuid('abcd', startedAt, ['agent.name']); - expect(signalUuid).toEqual('a4832768-a379-583a-b1a2-e2ce2ad9e6e9'); - }); - - it('should generate a uuid with key', () => { - const startedAt = new Date('2019-11-18T13:32:00Z'); - const signalUuid = calculateThresholdSignalUuid('abcd', startedAt, ['host.ip'], '1.2.3.4'); - expect(signalUuid).toEqual('ee8870dc-45ff-5e6c-a2f9-80886651ce03'); - }); - }); - describe('buildChunkedOrFilter', () => { test('should return undefined if no values are provided', () => { const filter = buildChunkedOrFilter('field.name', []); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts similarity index 95% rename from x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts rename to x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts index 1899b02811194..711db3dc1e601 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts @@ -7,7 +7,6 @@ import { createHash } from 'crypto'; import { chunk, get, invert, isEmpty, partition } from 'lodash'; import moment from 'moment'; -import { v5 as uuidv5 } from 'uuid'; import dateMath from '@kbn/datemath'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; @@ -31,9 +30,9 @@ import type { } from '@kbn/alerting-plugin/server'; import { parseDuration } from '@kbn/alerting-plugin/server'; import type { ExceptionListClient, ListClient, ListPluginSetup } from '@kbn/lists-plugin/server'; -import type { TimestampOverride } from '../../../../common/detection_engine/rule_schema'; -import type { Privilege } from '../../../../common/detection_engine/schemas/common'; -import { RuleExecutionStatus } from '../../../../common/detection_engine/rule_monitoring'; +import type { TimestampOverride } from '../../../../../common/detection_engine/rule_schema'; +import type { Privilege } from '../../../../../common/detection_engine/schemas/common'; +import { RuleExecutionStatus } from '../../../../../common/detection_engine/rule_monitoring'; import type { BulkResponseErrorAggregation, SignalHit, @@ -46,8 +45,8 @@ import type { SignalSourceHit, SimpleHit, WrappedEventHit, -} from './types'; -import type { ShardError } from '../../types'; +} from '../types'; +import type { ShardError } from '../../../types'; import type { EqlRuleParams, MachineLearningRuleParams, @@ -55,16 +54,16 @@ import type { RuleParams, ThreatRuleParams, ThresholdRuleParams, -} from '../rule_schema'; -import type { BaseHit, SearchTypes } from '../../../../common/detection_engine/types'; -import type { IRuleExecutionLogForExecutors } from '../rule_monitoring'; -import { withSecuritySpan } from '../../../utils/with_security_span'; +} from '../../rule_schema'; +import type { BaseHit, SearchTypes } from '../../../../../common/detection_engine/types'; +import type { IRuleExecutionLogForExecutors } from '../../rule_monitoring'; +import { withSecuritySpan } from '../../../../utils/with_security_span'; import type { BaseFieldsLatest, DetectionAlert, -} from '../../../../common/detection_engine/schemas/alerts'; -import { ENABLE_CCS_READ_WARNING_SETTING } from '../../../../common/constants'; -import type { GenericBulkCreateResponse } from '../rule_types/factories'; +} from '../../../../../common/detection_engine/schemas/alerts'; +import { ENABLE_CCS_READ_WARNING_SETTING } from '../../../../../common/constants'; +import type { GenericBulkCreateResponse } from '../factories'; export const MAX_RULE_GAP_RATIO = 4; @@ -833,40 +832,6 @@ export const calculateTotal = ( return prevTotalHits + nextTotalHits; }; -export const calculateThresholdSignalUuid = ( - ruleId: string, - startedAt: Date, - thresholdFields: string[], - key?: string -): string => { - // used to generate stable Threshold Signals ID when run with the same params - const NAMESPACE_ID = '0684ec03-7201-4ee0-8ee0-3a3f6b2479b2'; - - const startedAtString = startedAt.toISOString(); - const keyString = key ?? ''; - const baseString = `${ruleId}${startedAtString}${thresholdFields.join(',')}${keyString}`; - - return uuidv5(baseString, NAMESPACE_ID); -}; - -export const getThresholdTermsHash = ( - terms: Array<{ - field: string; - value: string; - }> -): string => { - return createHash('sha256') - .update( - terms - .sort((term1, term2) => (term1.field > term2.field ? 1 : -1)) - .map((term) => { - return `${term.field}:${term.value}`; - }) - .join(',') - ) - .digest('hex'); -}; - export const isEqlParams = (params: RuleParams): params is EqlRuleParams => params.type === 'eql'; export const isThresholdParams = (params: RuleParams): params is ThresholdRuleParams => params.type === 'threshold'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/threshold_signal_history.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/threshold_signal_history.mock.ts deleted file mode 100644 index 4c43bd9ee1bde..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/threshold_signal_history.mock.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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ThresholdSignalHistory } from '../types'; -import { getThresholdTermsHash } from '../utils'; - -export const sampleThresholdSignalHistory = (): ThresholdSignalHistory => { - const terms = [ - { - field: 'source.ip', - value: '127.0.0.1', - }, - { - field: 'host.name', - value: 'garden-gnomes', - }, - ]; - return { - [`${getThresholdTermsHash(terms)}`]: { - terms, - lastSignalTimestamp: new Date('2020-12-17T16:28:00Z').getTime(), - }, - }; -}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/utils.ts deleted file mode 100644 index 1e1ecbc12b444..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/utils.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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { - ThresholdNormalized, - ThresholdWithCardinality, -} from '../../../../../common/detection_engine/rule_schema'; - -export const shouldFilterByCardinality = ( - threshold: ThresholdNormalized -): threshold is ThresholdWithCardinality => !!threshold.cardinality?.length; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts deleted file mode 100644 index 877239af49a9a..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type moment from 'moment'; -import type { ESSearchResponse } from '@kbn/es-types'; -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import type { - RuleTypeState, - AlertInstanceState, - AlertInstanceContext, - RuleExecutorOptions as AlertingRuleExecutorOptions, - RuleExecutorServices, -} from '@kbn/alerting-plugin/server'; -import type { ListClient } from '@kbn/lists-plugin/server'; -import type { EcsFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map'; -import type { TypeOfFieldMap } from '@kbn/rule-registry-plugin/common/field_map'; -import type { Status } from '../../../../common/detection_engine/schemas/common/schemas'; -import type { - BaseHit, - RuleAlertAction, - SearchTypes, - EqlSequence, -} from '../../../../common/detection_engine/types'; -import type { ITelemetryEventsSender } from '../../telemetry/sender'; -import type { RuleParams, UnifiedQueryRuleParams } from '../rule_schema'; -import type { GenericBulkCreateResponse } from '../rule_types/factories'; -import type { BuildReasonMessage } from './reason_formatters'; -import type { - BaseFieldsLatest, - DetectionAlert, - WrappedFieldsLatest, -} from '../../../../common/detection_engine/schemas/alerts'; -import type { IRuleExecutionLogForExecutors } from '../rule_monitoring'; -import type { buildGroupByFieldAggregation } from './alert_suppression/build_group_by_field_aggregation'; -import type { RuleResponse } from '../../../../common/detection_engine/rule_schema'; -import type { EnrichEvents } from './enrichments/types'; -import type { BucketHistory } from './alert_suppression/group_and_bulk_create'; -import type { RunOpts } from '../rule_types/types'; - -export interface ThresholdResult { - terms?: Array<{ - field: string; - value: string; - }>; - cardinality?: Array<{ - field: string; - value: number; - }>; - count: number; - from: string; -} - -export interface ThresholdSignalHistoryRecord { - terms: Array<{ - field?: string; - value: SearchTypes; - }>; - lastSignalTimestamp: number; -} - -export interface ThresholdSignalHistory { - [hash: string]: ThresholdSignalHistoryRecord; -} - -export interface RuleRangeTuple { - to: moment.Moment; - from: moment.Moment; - maxSignals: number; -} - -/** - * SignalSource is being used as both a type for documents that match detection engine queries as well as - * for queries that could be on top of signals. In cases where it is matched against detection engine queries, - * '@timestamp' might not be there since it is not required and we have timestamp override capabilities. Also - * the signal addition object, "signal?: {" will not be there unless it's a conflicting field when we are running - * queries on events. - * - * For cases where we are running queries against signals (signals on signals) "@timestamp" should always be there - * and the "signal?: {" sub-object should always be there. - */ -export interface SignalSource { - [key: string]: SearchTypes; - '@timestamp'?: string; - signal?: { - /** - * "parent" is deprecated: new signals should populate "parents" instead. Both are optional - * until all signals with parent are gone and we can safely remove it. - * @deprecated Use parents instead - */ - parent?: Ancestor; - parents?: Ancestor[]; - ancestors: Ancestor[]; - group?: { - id: string; - index?: number; - }; - rule: { - id: string; - description?: string; - false_positives?: string[]; - immutable?: boolean; - }; - /** signal.depth was introduced in 7.10 and pre-7.10 signals do not have it. */ - depth?: number; - original_time?: string; - /** signal.reason was introduced in 7.15 and pre-7.15 signals do not have it. */ - reason?: string; - status?: string; - threshold_result?: ThresholdResult; - }; - kibana?: SearchTypes; -} - -export interface BulkItem { - create?: { - _index: string; - _type?: string; - _id: string; - _version: number; - result?: string; - _shards?: { - total: number; - successful: number; - failed: number; - }; - _seq_no?: number; - _primary_term?: number; - status: number; - error?: { - type: string; - reason: string; - index_uuid?: string; - shard: string; - index: string; - }; - }; -} - -export interface BulkResponse { - took: number; - errors: boolean; - items: BulkItem[]; -} - -export interface GetResponse { - _index: string; - _type: string; - _id: string; - _version: number; - _seq_no: number; - _primary_term: number; - found: boolean; - _source: SearchTypes; -} - -export type EventHit = Exclude, '@timestamp'> & { - '@timestamp': string; - [key: string]: SearchTypes; -}; -export type WrappedEventHit = BaseHit; - -export type SignalSearchResponse< - TAggregations = Record -> = estypes.SearchResponse; -export type SignalSourceHit = estypes.SearchHit; -export type AlertSourceHit = estypes.SearchHit; -export type WrappedSignalHit = BaseHit; -export type BaseSignalHit = estypes.SearchHit; - -export type RuleExecutorOptions = AlertingRuleExecutorOptions< - RuleParams, - RuleTypeState, - AlertInstanceState, - AlertInstanceContext ->; - -export interface Ancestor { - rule?: string; - id: string; - type: string; - index: string; - depth: number; -} - -export interface Signal { - _meta?: { - version: number; - }; - rule: RuleResponse; - /** - * @deprecated Use "parents" instead of "parent" - */ - parent?: Ancestor; - parents: Ancestor[]; - ancestors: Ancestor[]; - group?: { - id: string; - index?: number; - }; - original_time?: string; - original_event?: SearchTypes; - reason?: string; - status: Status; - threshold_result?: ThresholdResult; - original_signal?: SearchTypes; - depth: number; -} - -export interface SignalHit { - '@timestamp': string; - event: object; - signal: Signal; - [key: string]: SearchTypes; -} - -export interface AlertAttributes { - actions: RuleAlertAction[]; - alertTypeId: string; - enabled: boolean; - name: string; - tags: string[]; - createdBy: string; - createdAt: string; - updatedBy: string; - schedule: { - interval: string; - }; - throttle: string; - params: T; -} - -export type BulkResponseErrorAggregation = Record; - -export type SignalsEnrichment = (signals: SignalSourceHit[]) => Promise; - -export type BulkCreate = ( - docs: Array>, - maxAlerts?: number, - enrichEvents?: EnrichEvents -) => Promise>; - -export type SimpleHit = BaseHit<{ '@timestamp'?: string }>; - -export type WrapHits = ( - hits: Array>, - buildReasonMessage: BuildReasonMessage -) => Array>; - -export type WrapSequences = ( - sequences: Array>, - buildReasonMessage: BuildReasonMessage -) => Array>; - -export type RuleServices = RuleExecutorServices< - AlertInstanceState, - AlertInstanceContext, - 'default' ->; -export interface SearchAfterAndBulkCreateParams { - tuple: { - to: moment.Moment; - from: moment.Moment; - maxSignals: number; - }; - services: RuleServices; - listClient: ListClient; - exceptionsList: ExceptionListItemSchema[]; - ruleExecutionLogger: IRuleExecutionLogForExecutors; - eventsTelemetry: ITelemetryEventsSender | undefined; - inputIndexPattern: string[]; - pageSize: number; - filter: estypes.QueryDslQueryContainer; - buildReasonMessage: BuildReasonMessage; - enrichment?: SignalsEnrichment; - bulkCreate: BulkCreate; - wrapHits: WrapHits; - trackTotalHits?: boolean; - sortOrder?: estypes.SortOrder; - runtimeMappings: estypes.MappingRuntimeFields | undefined; - primaryTimestamp: string; - secondaryTimestamp?: string; -} - -export interface GroupAndBulkCreateParams { - runOpts: RunOpts; - services: RuleServices; - spaceId: string; - filter: estypes.QueryDslQueryContainer; - buildReasonMessage: BuildReasonMessage; - bucketHistory?: BucketHistory[]; - groupByFields: string[]; -} - -export interface SearchAfterAndBulkCreateReturnType { - success: boolean; - warning: boolean; - searchAfterTimes: string[]; - enrichmentTimes: string[]; - bulkCreateTimes: string[]; - lastLookBackDate: Date | null | undefined; - createdSignalsCount: number; - createdSignals: unknown[]; - errors: string[]; - warningMessages: string[]; -} - -export interface GroupAndBulkCreateReturnType extends SearchAfterAndBulkCreateReturnType { - state: { - suppressionGroupHistory: BucketHistory[]; - }; -} - -export interface MultiAggBucket { - cardinality?: Array<{ - field: string; - value: number; - }>; - terms: Array<{ - field: string; - value: string; - }>; - docCount: number; - maxTimestamp: string; - minTimestamp: string; -} - -export interface ThresholdAlertState extends RuleTypeState { - initialized: boolean; - signalHistory: ThresholdSignalHistory; -} - -export type EventGroupingMultiBucketAggregationResult = ESSearchResponse< - SignalSource, - { - body: { - aggregations: ReturnType; - }; - } ->; - -// the new fields can be added later if needed -export interface OverrideBodyQuery { - _source?: estypes.SearchSourceConfig; - fields?: estypes.Fields; -} diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index d0e97ba1298cf..dada95f662bbd 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -17,6 +17,7 @@ "exclude": [ "target/**/*", "**/cypress/**", + "public/management/cypress_endpoint.config.ts", ], "kbn_references": [ "@kbn/core", diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx index a7db1094ff262..4749e3c810116 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { EuiFilterGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useSelector } from 'react-redux'; -import { ServiceLocations } from '../../../../../../../common/runtime_types'; import { selectServiceLocationsState } from '../../../../state'; import { @@ -20,10 +19,6 @@ import { import { useFilters } from './use_filters'; import { FilterButton } from './filter_button'; -export const findLocationItem = (query: string, locations: ServiceLocations) => { - return locations.find(({ id, label }) => query === id || label === query); -}; - export const FilterGroup = ({ handleFilterChange, }: { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/list_filters.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/list_filters.tsx index 9e654da2078e3..4eec46469ca06 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/list_filters.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/list_filters.tsx @@ -5,14 +5,14 @@ * 2.0. */ -import React from 'react'; +import React, { memo } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { FilterGroup } from './filter_group'; import { SearchField } from '../search_field'; import { SyntheticsMonitorFilterChangeHandler } from './filter_fields'; -export function ListFilters({ +export const ListFilters = memo(function ({ handleFilterChange, }: { handleFilterChange: SyntheticsMonitorFilterChangeHandler; @@ -27,4 +27,4 @@ export function ListFilters({
); -} +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx index 45504ab27b4a6..05741f7aa0cac 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx @@ -40,7 +40,6 @@ describe('useMonitorList', () => { absoluteTotal: state.monitorList.data.absoluteTotal ?? 0, pageState: state.monitorList.pageState, syntheticsMonitors: selectEncryptedSyntheticsSavedMonitors.resultFunc(state.monitorList), - overviewStatus: null, handleFilterChange: jest.fn(), }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.ts index 2e200e983d0a5..2235121b05ad5 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.ts @@ -8,7 +8,6 @@ import { useCallback, useEffect, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useDebounce } from 'react-use'; -import { useOverviewStatus } from './use_overview_status'; import { fetchMonitorListAction, quietFetchMonitorListAction, @@ -27,8 +26,6 @@ export function useMonitorList() { const { pageState, loading, loaded, error, data } = useSelector(selectMonitorListState); const syntheticsMonitors = useSelector(selectEncryptedSyntheticsSavedMonitors); - const { status: overviewStatus } = useOverviewStatus(); - const { handleFilterChange } = useMonitorFiltersState(); const { lastRefresh } = useSyntheticsRefreshContext(); @@ -50,17 +47,20 @@ export function useMonitorList() { }, [lastRefresh]); // On initial mount, load the page - useEffect(() => { - if (isInitialMount.current) { - if (loaded) { - dispatch(quietFetchMonitorListAction(pageState)); - } else { - dispatch(fetchMonitorListAction.get(pageState)); + useDebounce( + () => { + if (isInitialMount.current) { + if (loaded) { + dispatch(quietFetchMonitorListAction(pageState)); + } else { + dispatch(fetchMonitorListAction.get(pageState)); + } } - } + }, + 100, // we don't use pageState here, for pageState, useDebounce will handle it - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [dispatch]); + [dispatch] + ); useDebounce( () => { @@ -86,7 +86,6 @@ export function useMonitorList() { loadPage, reloadPage, absoluteTotal: data.absoluteTotal ?? 0, - overviewStatus, handleFilterChange, }; } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts index b7671ce9d55b2..ed99ec8161765 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts @@ -15,7 +15,7 @@ import { selectOverviewStatus, } from '../../../state/overview_status'; -export function useOverviewStatus() { +export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLocation: boolean }) { const pageState = useSelector(selectOverviewPageState); const { status, error, loaded } = useSelector(selectOverviewStatus); @@ -24,16 +24,16 @@ export function useOverviewStatus() { const dispatch = useDispatch(); const reload = useCallback(() => { - dispatch(fetchOverviewStatusAction.get(pageState)); - }, [dispatch, pageState]); + dispatch(fetchOverviewStatusAction.get({ pageState, scopeStatusByLocation })); + }, [dispatch, pageState, scopeStatusByLocation]); useEffect(() => { if (loaded) { - dispatch(quietFetchOverviewStatusAction.get(pageState)); + dispatch(quietFetchOverviewStatusAction.get({ pageState, scopeStatusByLocation })); } else { reload(); } - }, [dispatch, reload, lastRefresh, pageState, loaded]); + }, [dispatch, reload, lastRefresh, pageState, loaded, scopeStatusByLocation]); return { status, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_container.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_container.tsx index 51b4932bdfe15..af5ddb09e7834 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_container.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_container.tsx @@ -8,11 +8,13 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; +import { useSelector } from 'react-redux'; import type { useMonitorList } from '../hooks/use_monitor_list'; import { MonitorAsyncError } from './monitor_errors/monitor_async_error'; import { ListFilters } from '../common/monitor_filters/list_filters'; import { MonitorList } from './monitor_list_table/monitor_list'; import { MonitorStats } from './monitor_stats/monitor_stats'; +import { selectOverviewStatus } from '../../../state/overview_status'; export const MonitorListContainer = ({ isEnabled, @@ -30,10 +32,11 @@ export const MonitorListContainer = ({ absoluteTotal, loadPage, reloadPage, - overviewStatus, handleFilterChange, } = monitorListProps; + const { status: overviewStatus } = useSelector(selectOverviewStatus); + // TODO: Display inline errors in the management table // const { errorSummaries, loading: errorsLoading } = useInlineErrors({ diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/monitors_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/monitors_page.tsx index 7f271efcdd876..ae9a03578ac22 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/monitors_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/monitors_page.tsx @@ -10,6 +10,7 @@ import { Redirect } from 'react-router-dom'; import { EuiButton, EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; import { useTrackPageview } from '@kbn/observability-plugin/public'; +import { useOverviewStatus } from './hooks/use_overview_status'; import { GETTING_STARTED_ROUTE } from '../../../../../common/constants'; import { ServiceAllowedWrapper } from '../common/wrappers/service_allowed_wrapper'; @@ -24,7 +25,7 @@ import { useMonitorListBreadcrumbs } from './hooks/use_breadcrumbs'; import { useMonitorList } from './hooks/use_monitor_list'; import * as labels from './management/labels'; -const MonitorPage: React.FC = () => { +const MonitorManagementPage: React.FC = () => { useTrackPageview({ app: 'synthetics', path: 'monitors' }); useTrackPageview({ app: 'synthetics', path: 'monitors', delay: 15000 }); @@ -37,6 +38,8 @@ const MonitorPage: React.FC = () => { enableSynthetics, } = useEnablement(); + useOverviewStatus({ scopeStatusByLocation: false }); + const monitorListProps = useMonitorList(); const { syntheticsMonitors, loading: monitorsLoading, absoluteTotal, loaded } = monitorListProps; @@ -91,6 +94,6 @@ const MonitorPage: React.FC = () => { export const MonitorsPageWithServiceAllowed = React.memo(() => ( - + )); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx index ad86c58dce782..f3b50f5bf86cc 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx @@ -76,6 +76,7 @@ interface Props { position: PopoverPosition; iconHasPanel?: boolean; iconSize?: 's' | 'xs'; + locationId?: string; } const CustomShadowPanel = styled(EuiPanel)<{ shadow: string }>` @@ -107,6 +108,7 @@ export function ActionsPopover({ position, iconHasPanel = true, iconSize = 's', + locationId, }: Props) { const euiShadow = useEuiShadow('l'); const dispatch = useDispatch(); @@ -117,7 +119,7 @@ export function ActionsPopover({ const detailUrl = useMonitorDetailLocator({ configId: monitor.configId, - locationId: monitor.location.id, + locationId: locationId ?? monitor.location.id, }); const editUrl = useEditMonitorLocator({ configId: monitor.configId }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx index f00e918f0b091..b34f4f6fe421a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx @@ -306,6 +306,7 @@ export function MonitorDetailFlyout(props: Props) { position="default" iconHasPanel={false} iconSize="xs" + locationId={locationId} /> )}
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx index ffcec3f0aeb74..77a29f735a40b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx @@ -20,7 +20,7 @@ import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useSelector } from 'react-redux'; import { selectOverviewStatus } from '../../../../state/overview_status'; import { AlertsLink } from '../../../common/links/view_alerts'; -import { useRefreshedRange } from '../../../../hooks'; +import { useRefreshedRange, useGetUrlParams } from '../../../../hooks'; import { ClientPluginsStart } from '../../../../../../plugin'; export const OverviewAlerts = () => { @@ -33,6 +33,8 @@ export const OverviewAlerts = () => { const { status } = useSelector(selectOverviewStatus); + const { locations } = useGetUrlParams(); + const loading = !status?.allIds || status?.allIds.length === 0; return ( @@ -66,6 +68,7 @@ export const OverviewAlerts = () => { status?.enabledMonitorQueryIds.length > 0 ? status?.enabledMonitorQueryIds : ['false-id'], + ...(locations?.length ? { 'observer.geo.name': locations } : {}), }, filters: [{ field: 'kibana.alert.status', values: ['active', 'recovered'] }], color: theme.eui.euiColorVis1, @@ -92,6 +95,7 @@ export const OverviewAlerts = () => { status?.enabledMonitorQueryIds.length > 0 ? status?.enabledMonitorQueryIds : ['false-id'], + ...(locations?.length ? { 'observer.geo.name': locations } : {}), }, dataType: 'alerts', selectedMetricField: RECORDS_FIELD, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx index 68548fa1af700..8f85b8bd90d43 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx @@ -18,7 +18,7 @@ import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { selectOverviewStatus } from '../../../../../state/overview_status'; import { OverviewErrorsSparklines } from './overview_errors_sparklines'; -import { useRefreshedRange } from '../../../../../hooks'; +import { useRefreshedRange, useGetUrlParams } from '../../../../../hooks'; import { OverviewErrorsCount } from './overview_errors_count'; export function OverviewErrors() { @@ -28,6 +28,8 @@ export function OverviewErrors() { const { from, to } = useRefreshedRange(6, 'hours'); + const params = useGetUrlParams(); + return ( @@ -43,6 +45,7 @@ export function OverviewErrors() { from={from} to={to} monitorIds={status?.enabledMonitorQueryIds ?? []} + locations={params.locations} />
@@ -50,6 +53,7 @@ export function OverviewErrors() { from={from} to={to} monitorIds={status?.enabledMonitorQueryIds ?? []} + locations={params.locations} /> diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx index 1d0ce0a90fc3b..582e6f1988076 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx @@ -16,13 +16,14 @@ interface MonitorErrorsCountProps { to: string; locationLabel?: string; monitorIds: string[]; + locations?: string[]; } export const OverviewErrorsCount = ({ monitorIds, from, to, - locationLabel, + locations, }: MonitorErrorsCountProps) => { const { observability } = useKibana().services; @@ -41,7 +42,7 @@ export const OverviewErrorsCount = ({ time, reportDefinitions: { 'monitor.id': monitorIds.length > 0 ? monitorIds : ['false-monitor-id'], - ...(locationLabel ? { 'observer.geo.name': [locationLabel] } : {}), + ...(locations?.length ? { 'observer.geo.name': locations } : {}), }, dataType: 'synthetics', selectedMetricField: 'monitor_errors', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx index 110aacad28a67..1a68495f63b3e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx @@ -15,8 +15,9 @@ interface Props { from: string; to: string; monitorIds: string[]; + locations?: string[]; } -export const OverviewErrorsSparklines = ({ from, to, monitorIds }: Props) => { +export const OverviewErrorsSparklines = ({ from, to, monitorIds, locations }: Props) => { const { observability } = useKibana().services; const { ExploratoryViewEmbeddable } = observability; @@ -38,6 +39,7 @@ export const OverviewErrorsSparklines = ({ from, to, monitorIds }: Props) => { seriesType: 'area', reportDefinitions: { 'monitor.id': monitorIds.length > 0 ? monitorIds : ['false-monitor-id'], + ...(locations?.length ? { 'observer.geo.name': locations } : {}), }, dataType: 'synthetics', selectedMetricField: 'monitor_errors', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx index 74f4539f3e91e..2842581994d83 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx @@ -21,7 +21,7 @@ function title(t?: number) { export function OverviewStatus() { const { statusFilter } = useGetUrlParams(); - const { status, error: statusError } = useOverviewStatus(); + const { status, error: statusError } = useOverviewStatus({ scopeStatusByLocation: true }); const dispatch = useDispatch(); const [statusConfig, setStatusConfig] = useState({ up: status?.up, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts index 0d068f05f3488..def068c7db03a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts @@ -100,11 +100,11 @@ export function* upsertMonitorEffect() { if (action.payload.shouldQuietFetchAfterSuccess !== false) { const monitorState = yield select(selectOverviewState); if (hasPageState(monitorState)) { + yield put(quietFetchOverviewAction.get(monitorState.pageState)); yield put( - quietFetchOverviewAction.get(monitorState.pageState as MonitorOverviewPageState) - ); - yield put( - quietFetchOverviewStatusAction.get(monitorState.pageState as MonitorOverviewPageState) + quietFetchOverviewStatusAction.get({ + pageState: monitorState.pageState, + }) ); } } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts index 62ac7190e7a09..0ca6e0c308f41 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts @@ -12,12 +12,12 @@ import { createAsyncAction } from '../utils/actions'; import { OverviewStatus } from '../../../../../common/runtime_types'; export const fetchOverviewStatusAction = createAsyncAction< - MonitorOverviewPageState, + { pageState: MonitorOverviewPageState; scopeStatusByLocation?: boolean }, OverviewStatus >('fetchOverviewStatusAction'); export const quietFetchOverviewStatusAction = createAsyncAction< - MonitorOverviewPageState, + { pageState: MonitorOverviewPageState; scopeStatusByLocation?: boolean }, OverviewStatus >('quietFetchOverviewStatusAction'); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/api.ts index 517fecb08c51c..84fc548a64878 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/api.ts @@ -11,9 +11,17 @@ import { OverviewStatus, OverviewStatusCodec } from '../../../../../common/runti import { apiService } from '../../../../utils/api_service'; import { toStatusOverviewQueryArgs } from '../overview/api'; -export const fetchOverviewStatus = async ( - pageState: MonitorOverviewPageState -): Promise => { +export const fetchOverviewStatus = async ({ + pageState, + scopeStatusByLocation, +}: { + pageState: MonitorOverviewPageState; + scopeStatusByLocation?: boolean; +}): Promise => { const params = toStatusOverviewQueryArgs(pageState); - return apiService.get(SYNTHETICS_API_URLS.OVERVIEW_STATUS, params, OverviewStatusCodec); + return apiService.get( + SYNTHETICS_API_URLS.OVERVIEW_STATUS, + { ...params, scopeStatusByLocation }, + OverviewStatusCodec + ); }; diff --git a/x-pack/plugins/synthetics/server/alert_rules/status_rule/status_rule_executor.ts b/x-pack/plugins/synthetics/server/alert_rules/status_rule/status_rule_executor.ts index 1e28763c60a2b..8e3a1948ef9dc 100644 --- a/x-pack/plugins/synthetics/server/alert_rules/status_rule/status_rule_executor.ts +++ b/x-pack/plugins/synthetics/server/alert_rules/status_rule/status_rule_executor.ts @@ -67,11 +67,11 @@ export class StatusRuleExecutor { } async getAllLocationNames() { - const { publicLocations, privateLocations } = await getAllLocations( - this.server, - this.syntheticsMonitorClient, - this.soClient - ); + const { publicLocations, privateLocations } = await getAllLocations({ + server: this.server, + syntheticsMonitorClient: this.syntheticsMonitorClient, + savedObjectsClient: this.soClient, + }); publicLocations.forEach((loc) => { this.locationIdNameMap[loc.label] = loc.id; diff --git a/x-pack/plugins/synthetics/server/legacy_uptime/routes/types.ts b/x-pack/plugins/synthetics/server/legacy_uptime/routes/types.ts index ed555ed90abd0..55286f8ea770e 100644 --- a/x-pack/plugins/synthetics/server/legacy_uptime/routes/types.ts +++ b/x-pack/plugins/synthetics/server/legacy_uptime/routes/types.ts @@ -109,15 +109,7 @@ export type UMRouteHandler = ({ subject?: Subject; }) => IKibanaResponse | Promise>; -export type SyntheticsRouteHandler = ({ - uptimeEsClient, - context, - request, - response, - server, - savedObjectsClient, - subject: Subject, -}: { +export interface RouteContext { uptimeEsClient: UptimeEsClient; context: UptimeRequestHandlerContext; request: SyntheticsRequest; @@ -126,7 +118,17 @@ export type SyntheticsRouteHandler = ({ server: UptimeServerSetup; syntheticsMonitorClient: SyntheticsMonitorClient; subject?: Subject; -}) => IKibanaResponse | Promise>; +} + +export type SyntheticsRouteHandler = ({ + uptimeEsClient, + context, + request, + response, + server, + savedObjectsClient, + subject: Subject, +}: RouteContext) => IKibanaResponse | Promise>; export type SyntheticsStreamingRouteHandler = ({ uptimeEsClient, diff --git a/x-pack/plugins/synthetics/server/routes/common.ts b/x-pack/plugins/synthetics/server/routes/common.ts index 2244e0296cf63..c536884e25c4e 100644 --- a/x-pack/plugins/synthetics/server/routes/common.ts +++ b/x-pack/plugins/synthetics/server/routes/common.ts @@ -6,11 +6,12 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; -import { SyntheticsService } from '../synthetics_service/synthetics_service'; +import { SavedObjectsFindResponse } from '@kbn/core/server'; +import { getAllLocations } from '../synthetics_service/get_all_locations'; import { EncryptedSyntheticsMonitor, ServiceLocations } from '../../common/runtime_types'; import { monitorAttributes } from '../../common/types/saved_objects'; import { syntheticsMonitorType } from '../legacy_uptime/lib/saved_objects/synthetics_monitor'; +import { RouteContext } from '../legacy_uptime/routes'; export const QuerySchema = schema.object({ page: schema.maybe(schema.number()), @@ -40,6 +41,7 @@ export const OverviewStatusSchema = schema.object({ projects: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), schedules: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), status: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), + scopeStatusByLocation: schema.maybe(schema.boolean()), }); export type OverviewStatusQuery = TypeOf; @@ -54,10 +56,8 @@ export const SEARCH_FIELDS = [ 'project_id.text', ]; -export const getMonitors = ( - request: MonitorsQuery, - syntheticsService: SyntheticsService, - savedObjectsClient: SavedObjectsClientContract +export const getMonitors = async ( + context: RouteContext ): Promise> => { const { perPage = 50, @@ -73,19 +73,19 @@ export const getMonitors = ( searchAfter, projects, schedules, - } = request as MonitorsQuery; + } = context.request.query as MonitorsQuery; - const filterStr = getMonitorFilters({ + const filterStr = await getMonitorFilters({ filter, monitorTypes, tags, locations, - serviceLocations: syntheticsService.locations, projects, schedules, + context, }); - return savedObjectsClient.find({ + return context.savedObjectsClient.find({ type: syntheticsMonitorType, perPage, page, @@ -99,15 +99,14 @@ export const getMonitors = ( }); }; -export const getMonitorFilters = ({ +export const getMonitorFilters = async ({ tags, - ports, filter, locations, projects, monitorTypes, schedules, - serviceLocations, + context, }: { filter?: string; tags?: string | string[]; @@ -115,10 +114,9 @@ export const getMonitorFilters = ({ locations?: string | string[]; projects?: string | string[]; schedules?: string | string[]; - ports?: string | string[]; - serviceLocations: ServiceLocations; + context: RouteContext; }) => { - const locationFilter = parseLocationFilter(serviceLocations, locations); + const locationFilter = await parseLocationFilter(context, locations); return [ filter, @@ -160,18 +158,20 @@ export const getKqlFilter = ({ return `${fieldKey}:"${values}"`; }; -const parseLocationFilter = (serviceLocations: ServiceLocations, locations?: string | string[]) => { - if (!locations) { +const parseLocationFilter = async (context: RouteContext, locations?: string | string[]) => { + if (!locations || locations?.length === 0) { return ''; } + const { allLocations } = await getAllLocations(context); + if (Array.isArray(locations)) { return locations - .map((loc) => findLocationItem(loc, serviceLocations)?.id ?? '') + .map((loc) => findLocationItem(loc, allLocations)?.id ?? '') .filter((val) => !!val); } - return findLocationItem(locations, serviceLocations)?.id ?? ''; + return findLocationItem(locations, allLocations)?.id ?? ''; }; export const findLocationItem = (query: string, locations: ServiceLocations) => { diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project_legacy.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project_legacy.ts index 28fe5761a359f..b68d2ac7aa58c 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project_legacy.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project_legacy.ts @@ -45,11 +45,11 @@ export const addSyntheticsProjectMonitorRouteLegacy: SyntheticsStreamingRouteFac const { id: spaceId } = await server.spaces.spacesService.getActiveSpace(request); const { keep_stale: keepStale, project: projectId } = request.body || {}; - const { publicLocations, privateLocations } = await getAllLocations( + const { publicLocations, privateLocations } = await getAllLocations({ server, syntheticsMonitorClient, - savedObjectsClient - ); + savedObjectsClient, + }); const encryptedSavedObjectsClient = server.encryptedSavedObjects.getClient(); const pushMonitorFormatter = new ProjectMonitorFormatterLegacy({ diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/delete_monitor_project.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/delete_monitor_project.ts index 9107180bfb1de..8a46dae9ff6a8 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/delete_monitor_project.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/delete_monitor_project.ts @@ -25,13 +25,8 @@ export const deleteSyntheticsMonitorProjectRoute: SyntheticsRestApiRouteFactory projectName: schema.string(), }), }, - handler: async ({ - request, - response, - savedObjectsClient, - server, - syntheticsMonitorClient, - }): Promise => { + handler: async (routeContext): Promise => { + const { request, response, savedObjectsClient, server, syntheticsMonitorClient } = routeContext; const { projectName } = request.params; const { monitors: monitorsToDelete } = request.body; const decodedProjectName = decodeURI(projectName); @@ -43,20 +38,20 @@ export const deleteSyntheticsMonitorProjectRoute: SyntheticsRestApiRouteFactory }); } - const { saved_objects: monitors } = await getMonitors( - { - filter: `${syntheticsMonitorType}.attributes.${ - ConfigKey.PROJECT_ID - }: "${decodedProjectName}" AND ${getKqlFilter({ - field: 'journey_id', - values: monitorsToDelete.map((id: string) => `${id}`), - })}`, - fields: [], - perPage: 500, + const deleteFilter = `${syntheticsMonitorType}.attributes.${ + ConfigKey.PROJECT_ID + }: "${decodedProjectName}" AND ${getKqlFilter({ + field: 'journey_id', + values: monitorsToDelete.map((id: string) => `${id}`), + })}`; + + const { saved_objects: monitors } = await getMonitors({ + ...routeContext, + request: { + ...request, + query: { ...request.query, filter: deleteFilter, fields: [], perPage: 500 }, }, - syntheticsMonitorClient.syntheticsService, - savedObjectsClient - ); + }); const { integrations: { writeIntegrationPolicies }, diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor.ts index 5adc119847e11..2557bf66db781 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor.ts @@ -65,7 +65,8 @@ export const getAllSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => validate: { query: QuerySchema, }, - handler: async ({ request, savedObjectsClient, syntheticsMonitorClient }): Promise => { + handler: async (routeContext): Promise => { + const { request, savedObjectsClient, syntheticsMonitorClient } = routeContext; const totalCountQuery = async () => { if (isMonitorsQueryFiltered(request.query)) { return savedObjectsClient.find({ @@ -77,7 +78,7 @@ export const getAllSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory = () => }; const [queryResult, totalCount] = await Promise.all([ - getMonitors(request.query, syntheticsMonitorClient.syntheticsService, savedObjectsClient), + getMonitors(routeContext), totalCountQuery(), ]); @@ -101,7 +102,9 @@ export const getSyntheticsMonitorOverviewRoute: SyntheticsRestApiRouteFactory = validate: { query: QuerySchema, }, - handler: async ({ request, savedObjectsClient, syntheticsMonitorClient }): Promise => { + handler: async (routeContext): Promise => { + const { request, savedObjectsClient } = routeContext; + const { sortField, sortOrder, @@ -109,9 +112,9 @@ export const getSyntheticsMonitorOverviewRoute: SyntheticsRestApiRouteFactory = locations: queriedLocations, } = request.query as MonitorsQuery; - const filtersStr = getMonitorFilters({ + const filtersStr = await getMonitorFilters({ ...request.query, - serviceLocations: syntheticsMonitorClient.syntheticsService.locations, + context: routeContext, }); const allMonitorConfigs = await getAllMonitors({ diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts index fc965b94cb096..b9d5b07b4d481 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts @@ -25,31 +25,33 @@ export const getSyntheticsProjectMonitorsRoute: SyntheticsRestApiRouteFactory = }), query: querySchema, }, - handler: async ({ - request, - response, - server: { logger }, - savedObjectsClient, - syntheticsMonitorClient, - }): Promise => { + handler: async (routeContext): Promise => { + const { + request, + server: { logger }, + } = routeContext; + const { projectName } = request.params; const { per_page: perPage = 500, search_after: searchAfter } = request.query; const decodedProjectName = decodeURI(projectName); const decodedSearchAfter = searchAfter ? decodeURI(searchAfter) : undefined; try { - const { saved_objects: monitors, total } = await getMonitors( - { - filter: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}: "${decodedProjectName}"`, - fields: [ConfigKey.JOURNEY_ID, ConfigKey.CONFIG_HASH], - perPage, - sortField: ConfigKey.JOURNEY_ID, - sortOrder: 'asc', - searchAfter: decodedSearchAfter ? [...decodedSearchAfter.split(',')] : undefined, + const { saved_objects: monitors, total } = await getMonitors({ + ...routeContext, + request: { + ...request, + query: { + ...request.query, + filter: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}: "${decodedProjectName}"`, + fields: [ConfigKey.JOURNEY_ID, ConfigKey.CONFIG_HASH], + perPage, + sortField: ConfigKey.JOURNEY_ID, + sortOrder: 'asc', + searchAfter: decodedSearchAfter ? [...decodedSearchAfter.split(',')] : undefined, + }, }, - syntheticsMonitorClient.syntheticsService, - savedObjectsClient - ); + }); const projectMonitors = monitors.map((monitor) => ({ journey_id: monitor.attributes[ConfigKey.JOURNEY_ID], hash: monitor.attributes[ConfigKey.CONFIG_HASH] || '', diff --git a/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts b/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts index 670ebcab2d73c..750727d85f7ce 100644 --- a/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts +++ b/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts @@ -6,20 +6,16 @@ */ import { intersection } from 'lodash'; import datemath, { Unit } from '@kbn/datemath'; -import { SavedObjectsClientContract } from '@kbn/core/server'; import moment from 'moment'; import { ConfigKey } from '../../../common/runtime_types'; import { getAllMonitors, processMonitors, } from '../../saved_objects/synthetics_monitor/get_all_monitors'; -import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters'; import { queryMonitorStatus } from '../../queries/query_monitor_status'; import { SYNTHETICS_API_URLS } from '../../../common/constants'; import { UMServerLibs } from '../../legacy_uptime/uptime_server'; -import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes'; -import { UptimeEsClient } from '../../legacy_uptime/lib/lib'; -import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client'; +import { RouteContext, SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes'; import { getMonitorFilters, OverviewStatusSchema, OverviewStatusQuery } from '../common'; /** @@ -40,14 +36,10 @@ export function periodToMs(schedule: { number: string; unit: Unit }) { * Subsequently, fetch the status for each monitor per location in the data streams. * @returns The counts of up/down/disabled monitor by location, and a map of each monitor:location status. */ -export async function getStatus( - server: UptimeServerSetup, - uptimeEsClient: UptimeEsClient, - soClient: SavedObjectsClientContract, - syntheticsMonitorClient: SyntheticsMonitorClient, - params: OverviewStatusQuery -) { - const { query, locations: queryLocations } = params; +export async function getStatus(context: RouteContext, params: OverviewStatusQuery) { + const { uptimeEsClient, syntheticsMonitorClient, savedObjectsClient, server } = context; + + const { query, locations: queryLocations, scopeStatusByLocation = true } = params; /** * Walk through all monitor saved objects, bucket IDs by disabled/enabled status. * @@ -55,12 +47,13 @@ export async function getStatus( * latest ping for all enabled monitors. */ - const filtersStr = getMonitorFilters({ + const filtersStr = await getMonitorFilters({ ...params, - serviceLocations: syntheticsMonitorClient.syntheticsService.locations, + context, }); + const allMonitors = await getAllMonitors({ - soClient, + soClient: savedObjectsClient, search: query ? `${query}*` : undefined, filter: filtersStr, fields: [ @@ -83,14 +76,15 @@ export async function getStatus( disabledMonitorsCount, projectMonitorsCount, monitorQueryIdToConfigIdMap, - } = await processMonitors(allMonitors, server, soClient, syntheticsMonitorClient); + } = await processMonitors(allMonitors, server, savedObjectsClient, syntheticsMonitorClient); // Account for locations filter const queryLocationsArray = queryLocations && !Array.isArray(queryLocations) ? [queryLocations] : queryLocations; - const listOfLocationAfterFilter = queryLocationsArray - ? intersection(listOfLocations, queryLocationsArray) - : listOfLocations; + const listOfLocationAfterFilter = + queryLocationsArray && scopeStatusByLocation + ? intersection(listOfLocations, queryLocationsArray) + : listOfLocations; const range = { from: moment().subtract(maxPeriod, 'milliseconds').subtract(20, 'minutes').toISOString(), @@ -128,20 +122,10 @@ export const createGetCurrentStatusRoute: SyntheticsRestApiRouteFactory = (libs: validate: { query: OverviewStatusSchema, }, - handler: async ({ - server, - uptimeEsClient, - savedObjectsClient, - syntheticsMonitorClient, - request, - }): Promise => { + handler: async (routeContext): Promise => { + const { request } = routeContext; + const params = request.query as OverviewStatusQuery; - return await getStatus( - server, - uptimeEsClient, - savedObjectsClient, - syntheticsMonitorClient, - params - ); + return await getStatus(routeContext, params); }, }); diff --git a/x-pack/plugins/synthetics/server/routes/synthetics_service/get_service_locations.ts b/x-pack/plugins/synthetics/server/routes/synthetics_service/get_service_locations.ts index 3f4f4fc72102c..7b4258ceb2a1a 100644 --- a/x-pack/plugins/synthetics/server/routes/synthetics_service/get_service_locations.ts +++ b/x-pack/plugins/synthetics/server/routes/synthetics_service/get_service_locations.ts @@ -14,14 +14,14 @@ export const getServiceLocationsRoute: SyntheticsRestApiRouteFactory = () => ({ path: API_URLS.SERVICE_LOCATIONS, validate: {}, handler: async ({ server, savedObjectsClient, syntheticsMonitorClient }): Promise => { - const { publicLocations, privateLocations, throttling } = await getAllLocations( + const { throttling, allLocations } = await getAllLocations({ server, syntheticsMonitorClient, - savedObjectsClient - ); + savedObjectsClient, + }); return { - locations: [...publicLocations, ...privateLocations], + locations: allLocations, throttling, }; }, diff --git a/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts b/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts index c8518823af95f..d134705093937 100644 --- a/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts +++ b/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts @@ -87,11 +87,11 @@ export const processMonitors = async ( const getLocationLabel = async (locationId: string) => { if (!allLocations) { - const { publicLocations, privateLocations } = await getAllLocations( + const { publicLocations, privateLocations } = await getAllLocations({ server, syntheticsMonitorClient, - soClient - ); + savedObjectsClient: soClient, + }); allLocations = [...publicLocations, ...privateLocations]; } diff --git a/x-pack/plugins/synthetics/server/synthetics_service/get_all_locations.ts b/x-pack/plugins/synthetics/server/synthetics_service/get_all_locations.ts index 41dbefa76a16e..d36e0928a62aa 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/get_all_locations.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/get_all_locations.ts @@ -10,20 +10,29 @@ import { getServiceLocations } from './get_service_locations'; import { SyntheticsMonitorClient } from './synthetics_monitor/synthetics_monitor_client'; import { UptimeServerSetup } from '../legacy_uptime/lib/adapters/framework'; -export async function getAllLocations( - server: UptimeServerSetup, - syntheticsMonitorClient: SyntheticsMonitorClient, - savedObjectsClient: SavedObjectsClientContract -) { +export async function getAllLocations({ + syntheticsMonitorClient, + savedObjectsClient, + server, +}: { + server: UptimeServerSetup; + syntheticsMonitorClient: SyntheticsMonitorClient; + savedObjectsClient: SavedObjectsClientContract; +}) { try { const [privateLocations, { locations: publicLocations, throttling }] = await Promise.all([ getPrivateLocations(syntheticsMonitorClient, savedObjectsClient), getServicePublicLocations(server, syntheticsMonitorClient), ]); - return { publicLocations, privateLocations, throttling }; + return { + publicLocations, + privateLocations, + throttling, + allLocations: [...publicLocations, ...privateLocations], + }; } catch (e) { server.logger.error(e); - return { publicLocations: [], privateLocations: [] }; + return { publicLocations: [], privateLocations: [], allLocations: [] }; } } diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts index 796b14307048c..f888ddd9f34d8 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts @@ -120,11 +120,11 @@ export class ProjectMonitorFormatter { } init = async () => { - const locationsPromise = getAllLocations( - this.server, - this.syntheticsMonitorClient, - this.savedObjectsClient - ); + const locationsPromise = getAllLocations({ + server: this.server, + syntheticsMonitorClient: this.syntheticsMonitorClient, + savedObjectsClient: this.savedObjectsClient, + }); const existingMonitorsPromise = this.getProjectMonitorsForProject(); const [locations, existingMonitors] = await Promise.all([ diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts index 31be90c6d7827..d8d79ea1dfb05 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts @@ -30,7 +30,6 @@ import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/syn export class SyntheticsMonitorClient { public syntheticsService: SyntheticsService; - public privateLocationAPI: SyntheticsPrivateLocation; constructor(syntheticsService: SyntheticsService, server: UptimeServerSetup) { diff --git a/x-pack/plugins/transform/public/app/common/pivot_aggs.ts b/x-pack/plugins/transform/public/app/common/pivot_aggs.ts index a1b8b6fefed0a..f22b5fcb264cc 100644 --- a/x-pack/plugins/transform/public/app/common/pivot_aggs.ts +++ b/x-pack/plugins/transform/public/app/common/pivot_aggs.ts @@ -32,7 +32,11 @@ export const TERMS_AGG_DEFAULT_SIZE = 10; export const pivotAggsFieldSupport = { [KBN_FIELD_TYPES.ATTACHMENT]: [PIVOT_SUPPORTED_AGGS.VALUE_COUNT, PIVOT_SUPPORTED_AGGS.FILTER], - [KBN_FIELD_TYPES.BOOLEAN]: [PIVOT_SUPPORTED_AGGS.VALUE_COUNT, PIVOT_SUPPORTED_AGGS.FILTER], + [KBN_FIELD_TYPES.BOOLEAN]: [ + PIVOT_SUPPORTED_AGGS.VALUE_COUNT, + PIVOT_SUPPORTED_AGGS.FILTER, + PIVOT_SUPPORTED_AGGS.TERMS, + ], [KBN_FIELD_TYPES.DATE]: [ PIVOT_SUPPORTED_AGGS.MAX, PIVOT_SUPPORTED_AGGS.MIN, @@ -58,6 +62,7 @@ export const pivotAggsFieldSupport = { PIVOT_SUPPORTED_AGGS.SUM, PIVOT_SUPPORTED_AGGS.VALUE_COUNT, PIVOT_SUPPORTED_AGGS.FILTER, + PIVOT_SUPPORTED_AGGS.TERMS, PIVOT_SUPPORTED_AGGS.TOP_METRICS, ], [KBN_FIELD_TYPES.STRING]: [ diff --git a/x-pack/plugins/transform/public/app/common/pivot_group_by.ts b/x-pack/plugins/transform/public/app/common/pivot_group_by.ts index 04f524a3f4163..9b557140d222b 100644 --- a/x-pack/plugins/transform/public/app/common/pivot_group_by.ts +++ b/x-pack/plugins/transform/public/app/common/pivot_group_by.ts @@ -27,13 +27,16 @@ export type PivotSupportedGroupByAggsWithInterval = export const pivotGroupByFieldSupport = { [KBN_FIELD_TYPES.ATTACHMENT]: [], - [KBN_FIELD_TYPES.BOOLEAN]: [], + [KBN_FIELD_TYPES.BOOLEAN]: [PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS], [KBN_FIELD_TYPES.DATE]: [PIVOT_SUPPORTED_GROUP_BY_AGGS.DATE_HISTOGRAM], [KBN_FIELD_TYPES.GEO_POINT]: [], [KBN_FIELD_TYPES.GEO_SHAPE]: [], [KBN_FIELD_TYPES.IP]: [PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS], [KBN_FIELD_TYPES.MURMUR3]: [], - [KBN_FIELD_TYPES.NUMBER]: [PIVOT_SUPPORTED_GROUP_BY_AGGS.HISTOGRAM], + [KBN_FIELD_TYPES.NUMBER]: [ + PIVOT_SUPPORTED_GROUP_BY_AGGS.HISTOGRAM, + PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS, + ], [KBN_FIELD_TYPES.STRING]: [PIVOT_SUPPORTED_GROUP_BY_AGGS.TERMS], [KBN_FIELD_TYPES._SOURCE]: [], [KBN_FIELD_TYPES.UNKNOWN]: [], diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts index e99f06a2d0222..9a816ef1fe111 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts @@ -6,7 +6,7 @@ */ import { getPivotDropdownOptions } from '.'; -import { DataView } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; import { FilterAggForm } from './filter_agg/components'; import type { RuntimeField } from '@kbn/data-views-plugin/common'; import { PercentilesAggForm } from './percentiles_agg/percentiles_form_component'; @@ -31,8 +31,8 @@ describe('Transform: Define Pivot Common', () => { } as DataView; const options = getPivotDropdownOptions(dataView); - expect(options).toMatchObject({ + fields: [{ name: ' the-f[i]e>ld ', type: 'number' }], aggOptions: [ { label: ' the-f[i]e>ld ', @@ -45,8 +45,10 @@ describe('Transform: Define Pivot Common', () => { { label: 'sum( the-f[i]e>ld )' }, { label: 'value_count( the-f[i]e>ld )' }, { label: 'filter( the-f[i]e>ld )' }, + { label: 'terms( the-f[i]e>ld )' }, { label: 'top_metrics( the-f[i]e>ld )' }, ], + field: { id: ' the-f[i]e>ld ', type: 'number' }, }, ], aggOptionsData: { @@ -101,8 +103,29 @@ describe('Transform: Define Pivot Common', () => { aggName: 'the-field.value_count', dropDownName: 'value_count( the-f[i]e>ld )', }, + 'terms( the-f[i]e>ld )': { + agg: 'terms', + field: ' the-f[i]e>ld ', + aggName: 'the-field.terms', + dropDownName: 'terms( the-f[i]e>ld )', + isSubAggsSupported: false, + isMultiField: false, + aggConfig: { size: 10 }, + }, + 'top_metrics( the-f[i]e>ld )': { + agg: 'top_metrics', + field: ' the-f[i]e>ld ', + aggName: 'top_metrics', + dropDownName: 'top_metrics( the-f[i]e>ld )', + isSubAggsSupported: false, + isMultiField: true, + aggConfig: {}, + }, }, - groupByOptions: [{ label: 'histogram( the-f[i]e>ld )' }], + groupByOptions: [ + { label: 'histogram( the-f[i]e>ld )', field: { id: ' the-f[i]e>ld ', type: 'number' } }, + { label: 'terms( the-f[i]e>ld )', field: { id: ' the-f[i]e>ld ', type: 'number' } }, + ], groupByOptionsData: { 'histogram( the-f[i]e>ld )': { agg: 'histogram', @@ -111,6 +134,12 @@ describe('Transform: Define Pivot Common', () => { dropDownName: 'histogram( the-f[i]e>ld )', interval: '10', }, + 'terms( the-f[i]e>ld )': { + agg: 'terms', + aggName: 'the-field', + dropDownName: 'terms( the-f[i]e>ld )', + field: ' the-f[i]e>ld ', + }, }, }); @@ -124,6 +153,10 @@ describe('Transform: Define Pivot Common', () => { }; const optionsWithRuntimeFields = getPivotDropdownOptions(dataView, runtimeMappings); expect(optionsWithRuntimeFields).toMatchObject({ + fields: [ + { name: ' the-f[i]e>ld ', type: 'number' }, + { name: 'rt_bytes_bigger', type: 'number' }, + ], aggOptions: [ { label: ' the-f[i]e>ld ', @@ -136,8 +169,10 @@ describe('Transform: Define Pivot Common', () => { { label: 'sum( the-f[i]e>ld )' }, { label: 'value_count( the-f[i]e>ld )' }, { label: 'filter( the-f[i]e>ld )' }, + { label: 'terms( the-f[i]e>ld )' }, { label: 'top_metrics( the-f[i]e>ld )' }, ], + field: { id: ' the-f[i]e>ld ', type: 'number' }, }, { label: 'rt_bytes_bigger', @@ -150,8 +185,10 @@ describe('Transform: Define Pivot Common', () => { { label: 'sum(rt_bytes_bigger)' }, { label: 'value_count(rt_bytes_bigger)' }, { label: 'filter(rt_bytes_bigger)' }, + { label: 'terms(rt_bytes_bigger)' }, { label: 'top_metrics(rt_bytes_bigger)' }, ], + field: { id: 'rt_bytes_bigger', type: 'number' }, }, ], aggOptionsData: { @@ -207,6 +244,24 @@ describe('Transform: Define Pivot Common', () => { isSubAggsSupported: true, AggFormComponent: FilterAggForm, }, + 'terms( the-f[i]e>ld )': { + agg: 'terms', + aggName: 'the-field.terms', + dropDownName: 'terms( the-f[i]e>ld )', + field: ' the-f[i]e>ld ', + isSubAggsSupported: false, + isMultiField: false, + aggConfig: { size: 10 }, + }, + 'top_metrics( the-f[i]e>ld )': { + agg: 'top_metrics', + aggName: 'top_metrics', + dropDownName: 'top_metrics( the-f[i]e>ld )', + field: ' the-f[i]e>ld ', + isSubAggsSupported: false, + isMultiField: true, + aggConfig: {}, + }, 'avg(rt_bytes_bigger)': { agg: 'avg', aggName: 'rt_bytes_bigger.avg', @@ -259,10 +314,30 @@ describe('Transform: Define Pivot Common', () => { isSubAggsSupported: true, AggFormComponent: FilterAggForm, }, + 'terms(rt_bytes_bigger)': { + agg: 'terms', + field: 'rt_bytes_bigger', + aggName: 'rt_bytes_bigger.terms', + dropDownName: 'terms(rt_bytes_bigger)', + isSubAggsSupported: false, + isMultiField: false, + aggConfig: { size: 10 }, + }, + 'top_metrics(rt_bytes_bigger)': { + agg: 'top_metrics', + field: 'rt_bytes_bigger', + aggName: 'top_metrics', + dropDownName: 'top_metrics(rt_bytes_bigger)', + isSubAggsSupported: false, + isMultiField: true, + aggConfig: {}, + }, }, groupByOptions: [ - { label: 'histogram( the-f[i]e>ld )' }, - { label: 'histogram(rt_bytes_bigger)' }, + { label: 'histogram( the-f[i]e>ld )', field: { id: ' the-f[i]e>ld ', type: 'number' } }, + { label: 'terms( the-f[i]e>ld )', field: { id: ' the-f[i]e>ld ', type: 'number' } }, + { label: 'histogram(rt_bytes_bigger)', field: { id: 'rt_bytes_bigger', type: 'number' } }, + { label: 'terms(rt_bytes_bigger)', field: { id: 'rt_bytes_bigger', type: 'number' } }, ], groupByOptionsData: { 'histogram( the-f[i]e>ld )': { @@ -272,6 +347,12 @@ describe('Transform: Define Pivot Common', () => { field: ' the-f[i]e>ld ', interval: '10', }, + 'terms( the-f[i]e>ld )': { + agg: 'terms', + field: ' the-f[i]e>ld ', + aggName: 'the-field', + dropDownName: 'terms( the-f[i]e>ld )', + }, 'histogram(rt_bytes_bigger)': { agg: 'histogram', aggName: 'rt_bytes_bigger', @@ -279,6 +360,12 @@ describe('Transform: Define Pivot Common', () => { field: 'rt_bytes_bigger', interval: '10', }, + 'terms(rt_bytes_bigger)': { + agg: 'terms', + field: 'rt_bytes_bigger', + aggName: 'rt_bytes_bigger', + dropDownName: 'terms(rt_bytes_bigger)', + }, }, }); }); diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx index e729b45342fb2..3aafa037b487d 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx @@ -304,7 +304,7 @@ export const StepDefineForm: FC = React.memo((props) => { 'xpack.transform.stepDefineForm.datePickerIconTipContent', { defaultMessage: - 'The time range will be applied to previews only and will not be part of the final transform configuration.', + 'The time range is applied to previews only and will not be part of the final transform configuration.', } )} /> diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/transform_function_selector.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/transform_function_selector.tsx index 6fbca6423c1cc..3aec137a3adf8 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/transform_function_selector.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/transform_function_selector.tsx @@ -23,7 +23,7 @@ export const TransformFunctionSelector: FC = ({ { name: TRANSFORM_FUNCTION.PIVOT, helpText: i18n.translate('xpack.transform.stepDefineForm.pivotHelperText', { - defaultMessage: 'Aggregate and group your data', + defaultMessage: 'Aggregate and group your data.', }), icon: 'aggregate', title: i18n.translate('xpack.transform.stepDefineForm.pivotLabel', { @@ -33,7 +33,7 @@ export const TransformFunctionSelector: FC = ({ { name: TRANSFORM_FUNCTION.LATEST, helpText: i18n.translate('xpack.transform.stepDefineForm.latestHelperText', { - defaultMessage: 'Keep track of your most recent data', + defaultMessage: 'Keep track of your most recent data.', }), icon: 'clock', title: i18n.translate('xpack.transform.stepDefineForm.latestLabel', { diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx index edad7b2932151..bc3f6b7fc5009 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx @@ -793,7 +793,7 @@ export const StepDetailsForm: FC = React.memo( } helpText={i18n.translate('xpack.transform.stepDetailsForm.frequencyHelpText', { defaultMessage: - 'The interval to check for changes in source indices when the transformation runs continuously.', + 'The interval to check for changes in source indices when the transform runs continuously.', })} > = ({ errorMessages={formFields.frequency.errorMessages} helpText={i18n.translate('xpack.transform.transformList.editFlyoutFormFrequencyHelpText', { defaultMessage: - 'The interval to check for changes in source indices when the transformation runs continuously.', + 'The interval to check for changes in source indices when the transform runs continuously.', })} label={i18n.translate('xpack.transform.transformList.editFlyoutFormFrequencyLabel', { defaultMessage: 'Frequency', diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 418dae07fcc58..7464ed2fbb4fe 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -4480,10 +4480,8 @@ "presentationUtil.labs.components.disabledStatusMessage": "Par défaut : {status}", "presentationUtil.labs.components.enabledStatusMessage": "Par défaut : {status}", "presentationUtil.labs.components.noProjectsinSolutionMessage": "Aucun atelier actuellement dans {solutionName}.", - "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "Créer {createType}", "presentationUtil.dashboardPicker.searchDashboardPlaceholder": "Recherche dans les tableaux de bord…", "presentationUtil.dataViewPicker.changeDataViewTitle": "Vue de données", - "presentationUtil.fieldPicker.noDataViewLabel": "Aucune vue de données sélectionnée", "presentationUtil.fieldPicker.noFieldsLabel": "Aucun champ correspondant", "presentationUtil.fieldSearch.fieldFilterButtonLabel": "Filtrer par type", "presentationUtil.fieldSearch.filterByTypeLabel": "Filtrer par type", @@ -4518,9 +4516,6 @@ "presentationUtil.saveModalDashboard.saveAndGoToDashboardLabel": "Enregistrer et accéder au tableau de bord", "presentationUtil.saveModalDashboard.saveLabel": "Enregistrer", "presentationUtil.saveModalDashboard.saveToLibraryLabel": "Enregistrer et ajouter à la bibliothèque", - "presentationUtil.solutionToolbar.editorMenuButtonLabel": "Tous les éditeurs", - "presentationUtil.solutionToolbar.libraryButtonLabel": "Ajouter depuis la bibliothèque", - "presentationUtil.solutionToolbar.quickButton.legendLabel": "Création rapide", "savedObjects.confirmModal.overwriteConfirmationMessage": "Êtes-vous sûr de vouloir écraser {title} ?", "savedObjects.confirmModal.overwriteTitle": "Écraser {name} ?", "savedObjects.confirmModal.saveDuplicateButtonLabel": "Enregistrer {name}", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e7fb5367a505c..f3c0b84e452b1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4478,10 +4478,8 @@ "presentationUtil.labs.components.disabledStatusMessage": "デフォルト: {status}", "presentationUtil.labs.components.enabledStatusMessage": "デフォルト: {status}", "presentationUtil.labs.components.noProjectsinSolutionMessage": "現在{solutionName}にはラボがありません。", - "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "新しい{createType}を作成", "presentationUtil.dashboardPicker.searchDashboardPlaceholder": "ダッシュボードを検索...", "presentationUtil.dataViewPicker.changeDataViewTitle": "データビュー", - "presentationUtil.fieldPicker.noDataViewLabel": "データビューが選択されていません", "presentationUtil.fieldPicker.noFieldsLabel": "一致するがフィールドがありません", "presentationUtil.fieldSearch.fieldFilterButtonLabel": "タイプでフィルタリング", "presentationUtil.fieldSearch.filterByTypeLabel": "タイプでフィルタリング", @@ -4516,9 +4514,6 @@ "presentationUtil.saveModalDashboard.saveAndGoToDashboardLabel": "保存してダッシュボードを開く", "presentationUtil.saveModalDashboard.saveLabel": "保存", "presentationUtil.saveModalDashboard.saveToLibraryLabel": "保存してライブラリに追加", - "presentationUtil.solutionToolbar.editorMenuButtonLabel": "すべてのエディター", - "presentationUtil.solutionToolbar.libraryButtonLabel": "ライブラリから追加", - "presentationUtil.solutionToolbar.quickButton.legendLabel": "クイック作成", "savedObjects.confirmModal.overwriteConfirmationMessage": "{title}を上書きしてよろしいですか?", "savedObjects.confirmModal.overwriteTitle": "{name} を上書きしますか?", "savedObjects.confirmModal.saveDuplicateButtonLabel": "{name} を保存", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 24783375ebe95..e8809adf47caf 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4483,10 +4483,8 @@ "presentationUtil.labs.components.disabledStatusMessage": "默认:{status}", "presentationUtil.labs.components.enabledStatusMessage": "默认:{status}", "presentationUtil.labs.components.noProjectsinSolutionMessage": "{solutionName} 中当前没有实验。", - "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "创建新的 {createType}", "presentationUtil.dashboardPicker.searchDashboardPlaceholder": "搜索仪表板......", "presentationUtil.dataViewPicker.changeDataViewTitle": "数据视图", - "presentationUtil.fieldPicker.noDataViewLabel": "未选择数据视图", "presentationUtil.fieldPicker.noFieldsLabel": "无匹配字段", "presentationUtil.fieldSearch.fieldFilterButtonLabel": "按类型筛选", "presentationUtil.fieldSearch.filterByTypeLabel": "按类型筛选", @@ -4521,9 +4519,6 @@ "presentationUtil.saveModalDashboard.saveAndGoToDashboardLabel": "保存并前往仪表板", "presentationUtil.saveModalDashboard.saveLabel": "保存", "presentationUtil.saveModalDashboard.saveToLibraryLabel": "保存并添加到库", - "presentationUtil.solutionToolbar.editorMenuButtonLabel": "所有编辑器", - "presentationUtil.solutionToolbar.libraryButtonLabel": "从库中添加", - "presentationUtil.solutionToolbar.quickButton.legendLabel": "快速创建", "savedObjects.confirmModal.overwriteConfirmationMessage": "确定要覆盖“{title}”?", "savedObjects.confirmModal.overwriteTitle": "覆盖“{name}”?", "savedObjects.confirmModal.saveDuplicateButtonLabel": "保存“{name}”", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.tsx index e2410801dd5b4..84e762cbe93f8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.tsx @@ -95,7 +95,10 @@ export function useBulkEditSelect(props: UseBulkEditSelectProps) { searchText, } = props; - const [state, dispatch] = useReducer(reducer, initialState); + const [state, dispatch] = useReducer(reducer, { + ...initialState, + selectedIds: new Set(), + }); const itemIds = useMemo(() => { return items.map((item) => item.id); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx index 6e9276018f9b9..d7737d3af99d8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx @@ -5,9 +5,17 @@ * 2.0. */ import * as React from 'react'; -import { ReactWrapper } from 'enzyme'; -import { act } from '@testing-library/react'; -import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { IToasts } from '@kbn/core/public'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { + render, + screen, + waitForElementToBeRemoved, + fireEvent, + act, + cleanup, +} from '@testing-library/react'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; import { ruleTypeRegistryMock } from '../../../rule_type_registry.mock'; import { RulesList } from './rules_list'; @@ -19,7 +27,6 @@ import { getDisabledByLicenseRuleTypeFromApi, ruleType, } from './test_helpers'; -import { IToasts } from '@kbn/core/public'; jest.mock('../../../../common/lib/kibana'); jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ @@ -85,7 +92,9 @@ jest.mock('../../../lib/capabilities', () => ({ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); - +const { loadRuleAggregationsWithKueryFilter } = jest.requireMock( + '../../../lib/rule_api/aggregate_kuery_filter' +); const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); const { bulkDeleteRules } = jest.requireMock('../../../lib/rule_api/bulk_delete'); @@ -99,58 +108,40 @@ ruleTypeRegistry.list.mockReturnValue([ruleType]); actionTypeRegistry.list.mockReturnValue([]); const useKibanaMock = useKibana as jest.Mocked; - -beforeEach(() => { - (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + cacheTime: 0, + }, + }, }); -// Test are too slow. It's breaking the build. So we skipp it now and waiting for improvment according this ticket: -// https://github.com/elastic/kibana/issues/145122 -describe.skip('Rules list bulk delete', () => { - let wrapper: ReactWrapper; +const AllTheProviders = ({ children }: { children: any }) => ( + + {children} + +); + +const renderWithProviders = (ui: any) => { + return render(ui, { wrapper: AllTheProviders }); +}; - async function setup(authorized: boolean = true) { +describe('Rules list Bulk Delete', () => { + beforeEach(async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); loadRulesWithKueryFilter.mockResolvedValue({ page: 1, perPage: 10000, total: 6, data: mockedRulesData, }); - - loadActionTypes.mockResolvedValue([ - { - id: 'test', - name: 'Test', - }, - { - id: 'test2', - name: 'Test2', - }, - ]); - loadRuleTypes.mockResolvedValue([ - ruleTypeFromApi, - getDisabledByLicenseRuleTypeFromApi(authorized), - ]); + loadActionTypes.mockResolvedValue([]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi, getDisabledByLicenseRuleTypeFromApi()]); loadAllActions.mockResolvedValue([]); - // eslint-disable-next-line react-hooks/rules-of-hooks + loadRuleAggregationsWithKueryFilter.mockResolvedValue({}); useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; - - // eslint-disable-next-line react-hooks/rules-of-hooks useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; - wrapper = mountWithIntl(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - } - - afterEach(() => { - jest.clearAllMocks(); - }); - - beforeAll(async () => { - await setup(); useKibanaMock().services.notifications.toasts = { addSuccess: jest.fn(), addError: jest.fn(), @@ -159,22 +150,27 @@ describe.skip('Rules list bulk delete', () => { } as unknown as IToasts; }); - beforeEach(() => { - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); - // Unselect something to test filtering - wrapper.find('[data-test-subj="checkboxSelectRow-2"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); + afterEach(() => { + jest.clearAllMocks(); + queryClient.clear(); + cleanup(); }); - it('can bulk delete', async () => { - wrapper.find('button[data-test-subj="bulkDelete"]').first().simulate('click'); - expect(wrapper.find('[data-test-subj="rulesDeleteConfirmation"]').exists()).toBeTruthy(); - wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); + beforeEach(async () => { + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + fireEvent.click(screen.getByTestId('selectAllRulesButton')); + fireEvent.click(screen.getByTestId('checkboxSelectRow-2')); + fireEvent.click(screen.getByTestId('showBulkActionButton')); + }); + + it('should Bulk Delete', async () => { + fireEvent.click(screen.getByTestId('bulkDelete')); + expect(screen.getByTestId('rulesDeleteConfirmation')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); }); const filter = bulkDeleteRules.mock.calls[0][0].filter; @@ -192,96 +188,68 @@ describe.skip('Rules list bulk delete', () => { ); }); - it('can cancel bulk delete', async () => { - wrapper.find('[data-test-subj="bulkDelete"]').first().simulate('click'); - expect(wrapper.find('[data-test-subj="rulesDeleteConfirmation"]').exists()).toBeTruthy(); - wrapper.find('[data-test-subj="confirmModalCancelButton"]').first().simulate('click'); - + it('should cancel Bulk Delete', async () => { + fireEvent.click(screen.getByTestId('bulkDelete')); + expect(screen.getByTestId('rulesDeleteConfirmation')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('confirmModalCancelButton')); }); - expect(bulkDeleteRules).not.toBeCalled(); }); - describe('Toast', () => { - it('should have success toast message', async () => { - wrapper.find('button[data-test-subj="bulkDelete"]').first().simulate('click'); - expect(wrapper.find('[data-test-subj="rulesDeleteConfirmation"]').exists()).toBeTruthy(); - wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); - expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledWith( - 'Deleted 10 rules' - ); - }); - - it('should have warning toast message', async () => { - bulkDeleteRules.mockResolvedValue({ - errors: [ - { - message: 'string', - rule: { - id: 'string', - name: 'string', - }, + it('should have warning toast message after Bulk Delete', async () => { + bulkDeleteRules.mockResolvedValue({ + errors: [ + { + message: 'string', + rule: { + id: 'string', + name: 'string', }, - ], - total: 10, - }); - - wrapper.find('button[data-test-subj="bulkDelete"]').first().simulate('click'); - expect(wrapper.find('[data-test-subj="rulesDeleteConfirmation"]').exists()).toBeTruthy(); - wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); - expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledWith( - expect.objectContaining({ - title: 'Deleted 9 rules, 1 rule encountered errors', - }) - ); + }, + ], + total: 10, }); - it('should have danger toast message', async () => { - bulkDeleteRules.mockResolvedValue({ - errors: [ - { - message: 'string', - rule: { - id: 'string', - name: 'string', - }, - }, - ], - total: 1, - }); + fireEvent.click(screen.getByTestId('bulkDelete')); + expect(screen.getByTestId('rulesDeleteConfirmation')).toBeInTheDocument(); + await act(async () => { + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); + }); - wrapper.find('button[data-test-subj="bulkDelete"]').first().simulate('click'); - expect(wrapper.find('[data-test-subj="rulesDeleteConfirmation"]').exists()).toBeTruthy(); - wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); + expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Deleted 9 rules, 1 rule encountered errors', + }) + ); + }); - await act(async () => { - await nextTick(); - wrapper.update(); - }); + it('should have danger toast message after Bulk Delete', async () => { + bulkDeleteRules.mockResolvedValue({ + errors: [ + { + message: 'string', + rule: { + id: 'string', + name: 'string', + }, + }, + ], + total: 1, + }); - expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledTimes(1); - expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledWith( - expect.objectContaining({ - title: 'Failed to delete 1 rule', - }) - ); + fireEvent.click(screen.getByTestId('bulkDelete')); + expect(screen.getByTestId('rulesDeleteConfirmation')).toBeInTheDocument(); + await act(async () => { + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); }); + + expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Failed to delete 1 rule', + }) + ); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx index eb3be548b59fe..0e6773ddd3092 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx @@ -5,9 +5,17 @@ * 2.0. */ import * as React from 'react'; -import { ReactWrapper } from 'enzyme'; -import { act } from '@testing-library/react'; -import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { IToasts } from '@kbn/core/public'; +import { + act, + render, + screen, + cleanup, + waitForElementToBeRemoved, + fireEvent, +} from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; import { ruleTypeRegistryMock } from '../../../rule_type_registry.mock'; import { RulesList } from './rules_list'; @@ -19,7 +27,6 @@ import { getDisabledByLicenseRuleTypeFromApi, ruleType, } from './test_helpers'; -import { IToasts } from '@kbn/core/public'; jest.mock('../../../../common/lib/kibana'); jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ @@ -30,7 +37,6 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadActionTypes: jest.fn(), loadAllActions: jest.fn(), })); - jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), })); @@ -55,10 +61,8 @@ jest.mock('../../../lib/rule_api/health', () => ({ hasPermanentEncryptionKey: true, })), })); - jest.mock('../../../lib/rule_api/aggregate_kuery_filter'); jest.mock('../../../lib/rule_api/rules_kuery_filter'); - jest.mock('../../../../common/lib/health_api', () => ({ triggersActionsUiHealth: jest.fn(() => ({ isRulesAvailable: true })), })); @@ -75,7 +79,6 @@ jest.mock('react-router-dom', () => ({ pathname: '/triggersActions/rules/', }), })); - jest.mock('../../../lib/capabilities', () => ({ hasAllPrivilege: jest.fn(() => true), hasSaveRulesCapability: jest.fn(() => true), @@ -85,6 +88,13 @@ jest.mock('../../../lib/capabilities', () => ({ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ + loadRuleAggregationsWithKueryFilter: jest.fn(), +})); + +const { loadRuleAggregationsWithKueryFilter } = jest.requireMock( + '../../../lib/rule_api/aggregate_kuery_filter' +); const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); const { bulkDisableRules } = jest.requireMock('../../../lib/rule_api/bulk_disable'); @@ -99,58 +109,40 @@ ruleTypeRegistry.list.mockReturnValue([ruleType]); actionTypeRegistry.list.mockReturnValue([]); const useKibanaMock = useKibana as jest.Mocked; - -beforeEach(() => { - (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + cacheTime: 0, + }, + }, }); -// Test are too slow. It's breaking the build. So we skipp it now and waiting for improvment according this ticket: -// https://github.com/elastic/kibana/issues/145122 -describe.skip('Rules list bulk disable', () => { - let wrapper: ReactWrapper; +const AllTheProviders = ({ children }: { children: any }) => ( + + {children} + +); + +const renderWithProviders = (ui: any) => { + return render(ui, { wrapper: AllTheProviders }); +}; - const setup = async (authorized: boolean = true) => { +describe('Rules list Bulk Disable', () => { + beforeAll(async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); loadRulesWithKueryFilter.mockResolvedValue({ page: 1, perPage: 10000, total: 6, data: mockedRulesData, }); - - loadActionTypes.mockResolvedValue([ - { - id: 'test', - name: 'Test', - }, - { - id: 'test2', - name: 'Test2', - }, - ]); - loadRuleTypes.mockResolvedValue([ - ruleTypeFromApi, - getDisabledByLicenseRuleTypeFromApi(authorized), - ]); + loadActionTypes.mockResolvedValue([]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi, getDisabledByLicenseRuleTypeFromApi()]); loadAllActions.mockResolvedValue([]); - // eslint-disable-next-line react-hooks/rules-of-hooks + loadRuleAggregationsWithKueryFilter.mockResolvedValue({}); useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; - - // eslint-disable-next-line react-hooks/rules-of-hooks useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; - wrapper = mountWithIntl(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - }; - - afterEach(() => { - jest.clearAllMocks(); - }); - - beforeAll(async () => { - await setup(); useKibanaMock().services.notifications.toasts = { addSuccess: jest.fn(), addError: jest.fn(), @@ -159,20 +151,25 @@ describe.skip('Rules list bulk disable', () => { } as unknown as IToasts; }); - beforeEach(() => { - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); - // Unselect something to test filtering - wrapper.find('[data-test-subj="checkboxSelectRow-2"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); + afterEach(() => { + jest.clearAllMocks(); + queryClient.clear(); + cleanup(); }); - it.skip('can bulk disable', async () => { - wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); + beforeEach(async () => { + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + fireEvent.click(screen.getByTestId('selectAllRulesButton')); + fireEvent.click(screen.getByTestId('checkboxSelectRow-2')); + fireEvent.click(screen.getByTestId('showBulkActionButton')); + }); + it('can bulk disable', async () => { await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkDisable')); }); const filter = bulkDisableRules.mock.calls[0][0].filter; @@ -188,19 +185,16 @@ describe.skip('Rules list bulk disable', () => { ids: [], }) ); - expect( - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').first().prop('checked') - ).toBeFalsy(); - expect(wrapper.find('button[data-test-subj="bulkDisable"]').exists()).toBeFalsy(); + expect(screen.getByTestId('checkboxSelectRow-1').closest('tr')).not.toHaveClass( + 'euiTableRow-isSelected' + ); + expect(screen.queryByTestId('bulkDisable')).not.toBeInTheDocument(); }); describe('Toast', () => { it('should have success toast message', async () => { - wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkDisable')); }); expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); @@ -223,11 +217,8 @@ describe.skip('Rules list bulk disable', () => { total: 10, }); - wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkDisable')); }); expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); @@ -252,11 +243,8 @@ describe.skip('Rules list bulk disable', () => { total: 1, }); - wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkDisable')); }); expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx index 392ebdd8ca48c..40204483e430b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx @@ -5,9 +5,6 @@ * 2.0. */ import * as React from 'react'; -import { ReactWrapper } from 'enzyme'; -import { act } from '@testing-library/react'; -import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; import { ruleTypeRegistryMock } from '../../../rule_type_registry.mock'; import { RulesList } from './rules_list'; @@ -19,6 +16,10 @@ import { getDisabledByLicenseRuleTypeFromApi, ruleType, } from './test_helpers'; +import { IToasts } from '@kbn/core/public'; +import { act, render, screen, waitForElementToBeRemoved, fireEvent } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; jest.mock('../../../../common/lib/kibana'); jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ @@ -29,7 +30,6 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadActionTypes: jest.fn(), loadAllActions: jest.fn(), })); - jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), })); @@ -60,10 +60,8 @@ jest.mock('../../../lib/rule_api/health', () => ({ hasPermanentEncryptionKey: true, })), })); - jest.mock('../../../lib/rule_api/aggregate_kuery_filter'); jest.mock('../../../lib/rule_api/rules_kuery_filter'); - jest.mock('../../../../common/lib/health_api', () => ({ triggersActionsUiHealth: jest.fn(() => ({ isRulesAvailable: true })), })); @@ -80,7 +78,6 @@ jest.mock('react-router-dom', () => ({ pathname: '/triggersActions/rules/', }), })); - jest.mock('../../../lib/capabilities', () => ({ hasAllPrivilege: jest.fn(() => true), hasSaveRulesCapability: jest.fn(() => true), @@ -90,7 +87,13 @@ jest.mock('../../../lib/capabilities', () => ({ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ + loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +const { loadRuleAggregationsWithKueryFilter } = jest.requireMock( + '../../../lib/rule_api/aggregate_kuery_filter' +); const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); const { bulkSnoozeRules } = jest.requireMock('../../../lib/rule_api/snooze'); const { bulkUnsnoozeRules } = jest.requireMock('../../../lib/rule_api/unsnooze'); @@ -106,116 +109,73 @@ ruleTypeRegistry.list.mockReturnValue([ruleType]); actionTypeRegistry.list.mockReturnValue([]); const useKibanaMock = useKibana as jest.Mocked; - -beforeEach(() => { - (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + cacheTime: 0, + }, + }, }); -describe.skip('Rules list bulk actions', () => { - let wrapper: ReactWrapper; +const AllTheProviders = ({ children }: { children: any }) => ( + + {children} + +); + +const renderWithProviders = (ui: any) => { + return render(ui, { wrapper: AllTheProviders }); +}; - async function setup(authorized: boolean = true) { +describe('Rules list Bulk Edit', () => { + beforeAll(async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); loadRulesWithKueryFilter.mockResolvedValue({ page: 1, perPage: 10000, total: 6, data: mockedRulesData, }); - - loadActionTypes.mockResolvedValue([ - { - id: 'test', - name: 'Test', - }, - { - id: 'test2', - name: 'Test2', - }, - ]); - loadRuleTypes.mockResolvedValue([ - ruleTypeFromApi, - getDisabledByLicenseRuleTypeFromApi(authorized), - ]); + loadActionTypes.mockResolvedValue([]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi, getDisabledByLicenseRuleTypeFromApi()]); loadAllActions.mockResolvedValue([]); - // eslint-disable-next-line react-hooks/rules-of-hooks + loadRuleAggregationsWithKueryFilter.mockResolvedValue({}); useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; - - // eslint-disable-next-line react-hooks/rules-of-hooks useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; - wrapper = mountWithIntl(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - } + useKibanaMock().services.notifications.toasts = { + addSuccess: jest.fn(), + addError: jest.fn(), + addDanger: jest.fn(), + addWarning: jest.fn(), + } as unknown as IToasts; + }); afterEach(() => { jest.clearAllMocks(); - }); - - it('renders select all button for bulk editing', async () => { - await setup(); - expect(wrapper.find('[data-test-subj="totalRulesCount"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="showBulkActionButton"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="selectAllRulesButton"]').exists()).toBeFalsy(); - - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - - expect(wrapper.find('[data-test-subj="totalRulesCount"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="showBulkActionButton"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="selectAllRulesButton"]').exists()).toBeTruthy(); - }); - - it('does not render select all button if the user is not authorized', async () => { - await setup(false); - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - expect(wrapper.find('[data-test-subj="showBulkActionButton"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="selectAllRulesButton"]').exists()).toBeFalsy(); - }); - - it('selects all will select all items', async () => { - await setup(); - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); - - mockedRulesData.forEach((rule) => { - expect( - wrapper.find(`[data-test-subj="checkboxSelectRow-${rule.id}"]`).first().prop('checked') - ).toBeTruthy(); - }); - - wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); - - expect(wrapper.find('[data-test-subj="ruleQuickEditButton"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="disableAll"]').first().prop('isDisabled')).toBeTruthy(); - expect(wrapper.find('[data-test-subj="bulkDelete"]').exists()).toBeTruthy(); + queryClient.clear(); }); describe('bulk actions', () => { - beforeAll(async () => { - await setup(); - }); - - beforeEach(() => { - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); - // Unselect something to test filtering - wrapper.find('[data-test-subj="checkboxSelectRow-2"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); + beforeEach(async () => { + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + fireEvent.click(screen.getByTestId('selectAllRulesButton')); + fireEvent.click(screen.getByTestId('checkboxSelectRow-2')); + fireEvent.click(screen.getByTestId('showBulkActionButton')); }); - it('can bulk snooze', async () => { - wrapper.find('[data-test-subj="bulkSnooze"]').first().simulate('click'); - expect(wrapper.find('[data-test-subj="snoozePanel"]').exists()).toBeTruthy(); - wrapper.find('[data-test-subj="linkSnooze1h"]').first().simulate('click'); - + it('can bulk add snooze schedule', async () => { + fireEvent.click(screen.getByTestId('bulkSnoozeSchedule')); + expect(screen.queryByTestId('ruleSnoozeScheduler')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('scheduler-saveSchedule')); }); const filter = bulkSnoozeRules.mock.calls[0][0].filter; + expect(filter.function).toEqual('and'); expect(filter.arguments[0].function).toEqual('or'); expect(filter.arguments[1].function).toEqual('not'); @@ -229,22 +189,11 @@ describe.skip('Rules list bulk actions', () => { ); }); - it('can bulk unsnooze', async () => { - wrapper.find('[data-test-subj="bulkUnsnooze"]').hostNodes().first().simulate('click'); - - expect( - wrapper.find('[data-test-subj="bulkUnsnoozeConfirmationModal"]').exists() - ).toBeTruthy(); - - wrapper - .find('[data-test-subj="confirmModalConfirmButton"]') - .hostNodes() - .first() - .simulate('click'); - + it('can bulk remove snooze schedule', async () => { + fireEvent.click(screen.getByTestId('bulkRemoveSnoozeSchedule')); + expect(screen.queryByTestId('bulkRemoveScheduleConfirmationModal')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); }); const filter = bulkUnsnoozeRules.mock.calls[0][0].filter; @@ -258,21 +207,16 @@ describe.skip('Rules list bulk actions', () => { expect(bulkUnsnoozeRules).toHaveBeenCalledWith( expect.objectContaining({ ids: [], + scheduleIds: [], }) ); }); - it('can bulk add snooze schedule', async () => { - wrapper.find('[data-test-subj="bulkSnoozeSchedule"]').hostNodes().first().simulate('click'); - expect(wrapper.find('[data-test-subj="ruleSnoozeScheduler"]').exists()).toBeTruthy(); - wrapper - .find('[data-test-subj="scheduler-saveSchedule"]') - .hostNodes() - .first() - .simulate('click'); + it('can bulk snooze', async () => { + fireEvent.click(screen.getByTestId('bulkSnooze')); + expect(screen.queryByTestId('snoozePanel')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('linkSnooze1h')); }); const filter = bulkSnoozeRules.mock.calls[0][0].filter; @@ -290,24 +234,11 @@ describe.skip('Rules list bulk actions', () => { ); }); - it('can bulk remove snooze schedule', async () => { - wrapper - .find('[data-test-subj="bulkRemoveSnoozeSchedule"]') - .hostNodes() - .first() - .simulate('click'); - expect( - wrapper.find('[data-test-subj="bulkRemoveScheduleConfirmationModal"]').exists() - ).toBeTruthy(); - wrapper - .find('[data-test-subj="confirmModalConfirmButton"]') - .hostNodes() - .first() - .simulate('click'); - + it('can bulk unsnooze', async () => { + fireEvent.click(screen.getByTestId('bulkUnsnooze')); + expect(screen.queryByTestId('bulkUnsnoozeConfirmationModal')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); }); const filter = bulkUnsnoozeRules.mock.calls[0][0].filter; @@ -321,22 +252,15 @@ describe.skip('Rules list bulk actions', () => { expect(bulkUnsnoozeRules).toHaveBeenCalledWith( expect.objectContaining({ ids: [], - scheduleIds: [], }) ); }); it('can bulk update API key', async () => { - wrapper.find('[data-test-subj="updateAPIKeys"]').hostNodes().first().simulate('click'); - expect(wrapper.find('[data-test-subj="updateApiKeyIdsConfirmation"]').exists()).toBeTruthy(); - wrapper - .find('[data-test-subj="confirmModalConfirmButton"]') - .hostNodes() - .first() - .simulate('click'); + fireEvent.click(screen.getByTestId('updateAPIKeys')); + expect(screen.queryByTestId('updateApiKeyIdsConfirmation')).toBeInTheDocument(); await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('confirmModalConfirmButton')); }); const filter = bulkUpdateAPIKey.mock.calls[0][0].filter; @@ -354,4 +278,51 @@ describe.skip('Rules list bulk actions', () => { ); }); }); + + it('renders select all button for bulk editing', async () => { + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + + expect(screen.queryByTestId('totalRulesCount')).toBeInTheDocument(); + expect(screen.queryByTestId('showBulkActionButton')).not.toBeInTheDocument(); + expect(screen.queryByTestId('selectAllRulesButton')).not.toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + + expect(screen.queryByTestId('totalRulesCount')).not.toBeInTheDocument(); + expect(screen.queryByTestId('showBulkActionButton')).toBeInTheDocument(); + expect(screen.queryByTestId('selectAllRulesButton')).toBeInTheDocument(); + }); + + it('selects all will select all items', async () => { + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + fireEvent.click(screen.getByTestId('selectAllRulesButton')); + + mockedRulesData.forEach((rule) => { + expect(screen.getByTestId(`checkboxSelectRow-${rule.id}`).closest('tr')).toHaveClass( + 'euiTableRow-isSelected' + ); + }); + + fireEvent.click(screen.getByTestId('showBulkActionButton')); + + expect(screen.queryByTestId('ruleQuickEditButton')).toBeInTheDocument(); + expect(screen.queryByTestId('bulkDisable')).toBeInTheDocument(); + expect(screen.queryByTestId('bulkEnable')).toBeInTheDocument(); + expect(screen.queryByTestId('bulkDelete')).toBeInTheDocument(); + }); + + it('does not render select all button if the user is not authorized', async () => { + loadRuleTypes.mockResolvedValue([ruleTypeFromApi, getDisabledByLicenseRuleTypeFromApi(false)]); + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + + expect(screen.queryByTestId('showBulkActionButton')).toBeInTheDocument(); + expect(screen.queryByTestId('selectAllRulesButton')).not.toBeInTheDocument(); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx index 0cc662a28a69e..9ca4d2b5a277d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx @@ -5,9 +5,17 @@ * 2.0. */ import * as React from 'react'; -import { ReactWrapper } from 'enzyme'; -import { act } from '@testing-library/react'; -import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { + act, + render, + screen, + cleanup, + waitForElementToBeRemoved, + fireEvent, +} from '@testing-library/react'; +import { IToasts } from '@kbn/core/public'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; import { ruleTypeRegistryMock } from '../../../rule_type_registry.mock'; import { RulesList } from './rules_list'; @@ -19,7 +27,6 @@ import { getDisabledByLicenseRuleTypeFromApi, ruleType, } from './test_helpers'; -import { IToasts } from '@kbn/core/public'; jest.mock('../../../../common/lib/kibana'); jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ @@ -30,7 +37,6 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadActionTypes: jest.fn(), loadAllActions: jest.fn(), })); - jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), })); @@ -55,10 +61,8 @@ jest.mock('../../../lib/rule_api/health', () => ({ hasPermanentEncryptionKey: true, })), })); - jest.mock('../../../lib/rule_api/aggregate_kuery_filter'); jest.mock('../../../lib/rule_api/rules_kuery_filter'); - jest.mock('../../../../common/lib/health_api', () => ({ triggersActionsUiHealth: jest.fn(() => ({ isRulesAvailable: true })), })); @@ -75,7 +79,6 @@ jest.mock('react-router-dom', () => ({ pathname: '/triggersActions/rules/', }), })); - jest.mock('../../../lib/capabilities', () => ({ hasAllPrivilege: jest.fn(() => true), hasSaveRulesCapability: jest.fn(() => true), @@ -85,10 +88,15 @@ jest.mock('../../../lib/capabilities', () => ({ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ + loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +const { loadRuleAggregationsWithKueryFilter } = jest.requireMock( + '../../../lib/rule_api/aggregate_kuery_filter' +); const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); const { bulkEnableRules } = jest.requireMock('../../../lib/rule_api/bulk_enable'); - const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); @@ -99,58 +107,40 @@ ruleTypeRegistry.list.mockReturnValue([ruleType]); actionTypeRegistry.list.mockReturnValue([]); const useKibanaMock = useKibana as jest.Mocked; - -beforeEach(() => { - (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + cacheTime: 0, + }, + }, }); -// Test are too slow. It's breaking the build. So we skipp it now and waiting for improvment according this ticket: -// https://github.com/elastic/kibana/issues/145122 -describe.skip('Rules list bulk enable', () => { - let wrapper: ReactWrapper; +const AllTheProviders = ({ children }: { children: any }) => ( + + {children} + +); - const setup = async (authorized: boolean = true) => { +const renderWithProviders = (ui: any) => { + return render(ui, { wrapper: AllTheProviders }); +}; + +describe('Rules list Bulk Enable', () => { + beforeAll(async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); loadRulesWithKueryFilter.mockResolvedValue({ page: 1, perPage: 10000, total: 6, - data: mockedRulesData.map((rule) => ({ ...rule, enabled: false })), + data: mockedRulesData, }); - - loadActionTypes.mockResolvedValue([ - { - id: 'test', - name: 'Test', - }, - { - id: 'test2', - name: 'Test2', - }, - ]); - loadRuleTypes.mockResolvedValue([ - ruleTypeFromApi, - getDisabledByLicenseRuleTypeFromApi(authorized), - ]); + loadActionTypes.mockResolvedValue([]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi, getDisabledByLicenseRuleTypeFromApi()]); loadAllActions.mockResolvedValue([]); - // eslint-disable-next-line react-hooks/rules-of-hooks + loadRuleAggregationsWithKueryFilter.mockResolvedValue({}); useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; - - // eslint-disable-next-line react-hooks/rules-of-hooks useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; - wrapper = mountWithIntl(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - }; - - afterEach(() => { - jest.clearAllMocks(); - }); - - beforeAll(async () => { - await setup(); useKibanaMock().services.notifications.toasts = { addSuccess: jest.fn(), addError: jest.fn(), @@ -159,22 +149,26 @@ describe.skip('Rules list bulk enable', () => { } as unknown as IToasts; }); - beforeEach(() => { - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); - // Unselect something to test filtering - wrapper.find('[data-test-subj="checkboxSelectRow-2"]').at(1).simulate('change'); - wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); + afterEach(() => { + jest.clearAllMocks(); + queryClient.clear(); + cleanup(); + }); + + beforeEach(async () => { + renderWithProviders(); + await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); + + fireEvent.click(screen.getByTestId('checkboxSelectRow-1')); + fireEvent.click(screen.getByTestId('selectAllRulesButton')); + fireEvent.click(screen.getByTestId('checkboxSelectRow-2')); + fireEvent.click(screen.getByTestId('showBulkActionButton')); }); it('can bulk enable', async () => { - wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkEnable')); }); - const filter = bulkEnableRules.mock.calls[0][0].filter; expect(filter.function).toEqual('and'); @@ -188,19 +182,16 @@ describe.skip('Rules list bulk enable', () => { ids: [], }) ); - expect( - wrapper.find('[data-test-subj="checkboxSelectRow-1"]').first().prop('checked') - ).toBeFalsy(); - expect(wrapper.find('button[data-test-subj="bulkEnable"]').exists()).toBeFalsy(); + expect(screen.getByTestId('checkboxSelectRow-1').closest('tr')).not.toHaveClass( + 'euiTableRow-isSelected' + ); + expect(screen.queryByTestId('bulkEnable')).not.toBeInTheDocument(); }); describe('Toast', () => { it('should have success toast message', async () => { - wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkEnable')); }); expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); @@ -223,11 +214,8 @@ describe.skip('Rules list bulk enable', () => { total: 10, }); - wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkEnable')); }); expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); @@ -252,11 +240,8 @@ describe.skip('Rules list bulk enable', () => { total: 1, }); - wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); - await act(async () => { - await nextTick(); - wrapper.update(); + fireEvent.click(screen.getByTestId('bulkEnable')); }); expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledTimes(1); diff --git a/x-pack/test/accessibility/apps/dashboard_controls.ts b/x-pack/test/accessibility/apps/dashboard_controls.ts index 8560b65b5fd34..b53a25d543680 100644 --- a/x-pack/test/accessibility/apps/dashboard_controls.ts +++ b/x-pack/test/accessibility/apps/dashboard_controls.ts @@ -11,6 +11,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); const testSubjects = getService('testSubjects'); const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['common', 'dashboard', 'home', 'dashboardControls']); const browser = getService('browser'); @@ -56,7 +57,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('Options control panel & dashboard with options control', async () => { - await testSubjects.click('field-picker-select-OriginCityName'); + await PageObjects.dashboardControls.controlsEditorSetfield('OriginCityName'); await a11y.testAppSnapshot(); await testSubjects.click('control-editor-save'); await a11y.testAppSnapshot(); diff --git a/x-pack/test/cases_api_integration/common/lib/alerts.ts b/x-pack/test/cases_api_integration/common/lib/alerts.ts index 5aadd7df90949..2914f6a17d509 100644 --- a/x-pack/test/cases_api_integration/common/lib/alerts.ts +++ b/x-pack/test/cases_api_integration/common/lib/alerts.ts @@ -10,7 +10,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ToolingLog } from '@kbn/tooling-log'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '@kbn/security-solution-plugin/common/constants'; import { DetectionAlert } from '@kbn/security-solution-plugin/common/detection_engine/schemas/alerts'; -import { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/enrichments/types'; +import { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/enrichments/types'; import { getRuleForSignalTesting, createRule, diff --git a/x-pack/test/cases_api_integration/common/lib/api/index.ts b/x-pack/test/cases_api_integration/common/lib/api/index.ts index 1c9534c84d04b..c15c19232edf6 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/index.ts @@ -38,7 +38,7 @@ import { CasesMetricsResponse, CasesBulkGetResponse, } from '@kbn/cases-plugin/common/api'; -import { SignalHit } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; +import { SignalHit } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/types'; import { ActionResult } from '@kbn/actions-plugin/server/types'; import { ESCasesConfigureAttributes } from '@kbn/cases-plugin/server/services/configure/types'; import { ESCaseAttributes } from '@kbn/cases-plugin/server/services/cases/types'; diff --git a/x-pack/test/defend_workflows_cypress/agent.ts b/x-pack/test/defend_workflows_cypress/agent.ts index c34eb728432c9..91bf42d8adcf6 100644 --- a/x-pack/test/defend_workflows_cypress/agent.ts +++ b/x-pack/test/defend_workflows_cypress/agent.ts @@ -21,6 +21,8 @@ export class AgentManager extends Manager { public async setup() { this.vmName = await enrollEndpointHost(); + + return this.vmName; } public cleanup() { diff --git a/x-pack/test/defend_workflows_cypress/runner.ts b/x-pack/test/defend_workflows_cypress/runner.ts index fddf7867ba28c..12831e785a56b 100644 --- a/x-pack/test/defend_workflows_cypress/runner.ts +++ b/x-pack/test/defend_workflows_cypress/runner.ts @@ -14,9 +14,11 @@ import { AgentManager } from './agent'; import { FleetManager } from './fleet_server'; import { getLatestAvailableAgentVersion } from './utils'; +type RunnerEnv = Record; + async function withFleetAgent( { getService }: FtrProviderContext, - runner: (runnerEnv: Record) => Promise + runner: (runnerEnv: RunnerEnv) => Promise ) { const log = getService('log'); const config = getService('config'); @@ -40,9 +42,9 @@ async function withFleetAgent( const agentManager = new AgentManager(log); await fleetManager.setup(); - await agentManager.setup(); + const agentVmName = await agentManager.setup(); try { - await runner({}); + await runner({ agentVmName }); } finally { agentManager.cleanup(); fleetManager.cleanup(); @@ -58,10 +60,16 @@ export async function DefendWorkflowsCypressVisualTestRunner(context: FtrProvide } export async function DefendWorkflowsCypressEndpointTestRunner(context: FtrProviderContext) { - await withFleetAgent(context, () => startDefendWorkflowsCypress(context, 'dw:endpoint:open')); + await withFleetAgent(context, (runnerEnv) => + startDefendWorkflowsCypress(context, 'dw:endpoint:open', runnerEnv) + ); } -function startDefendWorkflowsCypress(context: FtrProviderContext, cypressCommand: string) { +function startDefendWorkflowsCypress( + context: FtrProviderContext, + cypressCommand: 'dw:endpoint:open' | 'dw:open' | 'dw:run', + runnerEnv?: RunnerEnv +) { const log = context.getService('log'); const config = context.getService('config'); return withProcRunner(log, async (procs) => { @@ -91,6 +99,7 @@ function startDefendWorkflowsCypress(context: FtrProviderContext, cypressCommand hostname: config.get('servers.kibana.hostname'), port: config.get('servers.kibana.port'), }), + CYPRESS_ENDPOINT_VM_NAME: runnerEnv?.agentVmName, ...process.env, }, wait: true, diff --git a/x-pack/test/defend_workflows_cypress/utils.ts b/x-pack/test/defend_workflows_cypress/utils.ts index 2f0b8baa1e856..2f13105f9b364 100644 --- a/x-pack/test/defend_workflows_cypress/utils.ts +++ b/x-pack/test/defend_workflows_cypress/utils.ts @@ -7,7 +7,7 @@ import axios from 'axios'; import semver from 'semver'; -import { filter } from 'lodash'; +import { map } from 'lodash'; import { KbnClient } from '@kbn/test'; /** @@ -20,9 +20,7 @@ export const getLatestAvailableAgentVersion = async (kbnClient: KbnClient): Prom const kbnStatus = await kbnClient.status.get(); const agentVersions = await axios .get('https://artifacts-api.elastic.co/v1/versions') - .then((response) => - filter(response.data.versions, (versionString) => !versionString.includes('SNAPSHOT')) - ); + .then((response) => map(response.data.versions, (version) => version.split('-SNAPSHOT')[0])); let version = semver.maxSatisfying(agentVersions, `<=${kbnStatus.version.number}`) ?? diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/create_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/create_signals_migrations.ts index 5a5011f05aac5..4445e63b54aaf 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/create_signals_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/create_signals_migrations.ts @@ -14,7 +14,7 @@ import { } from '@kbn/security-solution-plugin/common/constants'; import { ROLES } from '@kbn/security-solution-plugin/common/test'; import { SIGNALS_TEMPLATE_VERSION } from '@kbn/security-solution-plugin/server/lib/detection_engine/routes/index/get_signals_template'; -import { Signal } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; +import { Signal } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts index 64d71539eb065..ced077145f5a9 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts @@ -17,7 +17,7 @@ import { flattenWithPrefix } from '@kbn/securitysolution-rules'; import { get } from 'lodash'; import { EqlRuleCreateProps } from '@kbn/security-solution-plugin/common/detection_engine/rule_schema'; -import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; +import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts index 446163e0fc05b..c77ac2049fde5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts @@ -26,7 +26,7 @@ import { v4 as uuidv4 } from 'uuid'; import { QueryRuleCreateProps } from '@kbn/security-solution-plugin/common/detection_engine/rule_schema'; import { RuleExecutionStatus } from '@kbn/security-solution-plugin/common/detection_engine/rule_monitoring'; -import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; +import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts index df9a4fbce88ff..0f92db72d3c2a 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts @@ -23,7 +23,7 @@ import { flattenWithPrefix } from '@kbn/securitysolution-rules'; import { ThreatMatchRuleCreateProps } from '@kbn/security-solution-plugin/common/detection_engine/rule_schema'; import { ENRICHMENT_TYPES } from '@kbn/security-solution-plugin/common/cti/constants'; -import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; +import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts index 45b24902e8bc5..3dc878c4e2ba0 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts @@ -14,7 +14,7 @@ import { } from '@kbn/rule-data-utils'; import { ThresholdRuleCreateProps } from '@kbn/security-solution-plugin/common/detection_engine/rule_schema'; -import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; +import { Ancestor } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, diff --git a/x-pack/test/detection_engine_api_integration/utils/get_preview_alerts.ts b/x-pack/test/detection_engine_api_integration/utils/get_preview_alerts.ts index 2d9cdc0137546..716f46dfcb815 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_preview_alerts.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_preview_alerts.ts @@ -8,7 +8,7 @@ import type { Client } from '@elastic/elasticsearch'; import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { DetectionAlert } from '@kbn/security-solution-plugin/common/detection_engine/schemas/alerts'; -import { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/enrichments/types'; +import { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/enrichments/types'; import { refreshIndex } from './refresh_index'; /** diff --git a/x-pack/test/detection_engine_api_integration/utils/get_signals_by_ids.ts b/x-pack/test/detection_engine_api_integration/utils/get_signals_by_ids.ts index faea391b18602..d5740d91934eb 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_signals_by_ids.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_signals_by_ids.ts @@ -9,7 +9,7 @@ import { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey' import type { ToolingLog } from '@kbn/tooling-log'; import type SuperTest from 'supertest'; import type { DetectionAlert } from '@kbn/security-solution-plugin/common/detection_engine/schemas/alerts'; -import type { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/enrichments/types'; +import type { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/enrichments/types'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '@kbn/security-solution-plugin/common/constants'; import { countDownTest } from './count_down_test'; diff --git a/x-pack/test/fleet_api_integration/apis/epm/index.js b/x-pack/test/fleet_api_integration/apis/epm/index.js index 48af135f15ae2..867ab6f6fe3e4 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/index.js +++ b/x-pack/test/fleet_api_integration/apis/epm/index.js @@ -32,5 +32,6 @@ export default function loadTests({ loadTestFile }) { loadTestFile(require.resolve('./install_error_rollback')); loadTestFile(require.resolve('./final_pipeline')); loadTestFile(require.resolve('./custom_ingest_pipeline')); + loadTestFile(require.resolve('./verification_key_id')); }); } diff --git a/x-pack/test/fleet_api_integration/apis/epm/verification_key_id.ts b/x-pack/test/fleet_api_integration/apis/epm/verification_key_id.ts new file mode 100644 index 0000000000000..4c5468f35606e --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/epm/verification_key_id.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('EPM - verification key id', async () => { + it('returns the verification key ID ', async () => { + const res = await supertest + .get('/api/fleet/epm/verification_key_id') + .set('kbn-xsrf', 'xxx') + .expect(200); + + expect(res.body.id).equal('d2a182a7b0e00c14'); + }); + }); +} diff --git a/yarn.lock b/yarn.lock index 8d70855b7f7bb..52c769ade03a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12927,10 +12927,10 @@ cypress-recurse@^1.27.0: dependencies: humanize-duration "^3.27.3" -cypress@^12.5.1: - version "12.5.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.5.1.tgz#effdcccdd5a6187d61d497300903d4f3b5b21b6e" - integrity sha512-ZmCmJ3lsyeOpBfh410m5+AO2CO1AxAzFBt7k6/uVbNcrNZje1vdiwYTpj2ksPKg9mjr9lR6V8tmlDNMvr4H/YQ== +cypress@^12.6.0: + version "12.6.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.6.0.tgz#d71a82639756173c0682b3d467eb9f0523460e91" + integrity sha512-WdHSVaS1lumSd5XpVTslZd8ui9GIGphrzvXq9+3DtVhqjRZC5M70gu5SW/Y/SLPq3D1wiXGZoHC6HJ7ESVE2lw== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" @@ -12949,7 +12949,7 @@ cypress@^12.5.1: commander "^5.1.0" common-tags "^1.8.0" dayjs "^1.10.4" - debug "^4.3.2" + debug "^4.3.4" enquirer "^2.3.6" eventemitter2 "6.4.7" execa "4.1.0"